Running an EFI application automatically on boot - uefi

I can build and manually execute an EFI application in a UEFI environment. But, I'd like to have my application executed automatically at boot time.
Is there a way to tell the bootloader to do this or do I need to turn my application in to a driver to have it automatically executed? Is there maybe some entry in an FDF, DEC, DSC, or INF file I'm missing?

You can add a startup.nsh script file to your UEFI Shell boot drive that calls you application.
The following link should serve as a handy reference for working with scripts in the shell: UEFI Shells and Scripting. Look at section 3 (EFI Shell Scripts) specifically.
However, if you are actually building your own firmware, you can also look at creating a bootable EFI image and set your default boot option to this binary. This is most useful if you are including the binary as a part of your ROM, but it might be a little involved to set up the filesystem so that it is seen as a normal boot option.
Also, if you have complete access to your firmware source, you could also just load and call your binary from your BDS driver. I don't recommend this route, unless you are specifically aiming to create a standalone device that will never boot any other image.

#NicholasEmbry answer contain almost all what is needed, but I would like to clarify some things and add recent improvements in that area.
Adding UEFI application image to boot option is actually best known method when you don't have source code of your firmware, what is typical situation. You don't have to create any special bootable image it should be simple UEFI application image, what means that your INF should contain:
MODULE_TYPE = UEFI_APPLICATION
This option is not just for Option ROMs this is for all UEFI readable medium. For example you can create FAT32 partition on your storage (no matter if it is USB, HDD, SSD, etc. it just have to be readable by firmware) and place application image on this partition. Then boot to UEFI Shell and use bcfg command to affect your boot order.
bcfg command can be blocked by you BIOS vendor. In that situation please follow procedure from this post. This is booting rEFInd using USB stick. rEFInd contain bcfg tool and give you ability to use it.
How to use bcfg ?
All is described in help help bcfg -b. -b is UEFI pager. For those who like shortcuts, this command will display all boot options in system:
bcfg boot dump -v
You can add your application using command:
bcfg boot add <boot_pos> <path_to_uefi_image> <boot_order_name>
<boot_pos> - position in boot order. Note you usually want to put your application before OS. If there is no free boot option number before your OS you can of course move your OS one option down bcfg boot mv <old_pos> <new_pos> and then add your application image in between.
<path_to_uefi_image> - path to your UEFI image. This is UEFI readable path ie. fs0:\foobar.efi
<boot_order_name> - this is how you application will be visible in boot BIOS menu

Related

Machinecode and hardware

first of all hello to all hope you are good and safe.
well i have some questions about machine code and hardware and operating system.
1- i was search about how is pure machine code and i find somethings in here and net but not enough to answer my questions since im new to low level programming language. so how to write a pure machine code like open just my computer with 0,1 are machine code have any file extensions like assembly and .exe i wana write code just directly get area in ram and talk with processor and do what i writed for example open my computer or open a text file for example. so i wana know how to do it are pure machine code have a file extension like .exe or .asm
2- i know each cpu have it owen machine language somethigns is different on them it could not be a way to all cpu's undrestand our machine code. also i wana know for example we have 2 cpu both of them are x64 or x32 but 1 of them are windows other is linux are machine code of x64 windows will work also on x64 cpu linux?
thank you for give your time to me and read.
for now gathering information
An operating system provides the capability to run programs.  So, one program, like the desktop or command line shell, can ask the operating system to run another program.
When that happens, the operating system creates an environment to run the program called a process, and then loads a program file from disc into the process, and directs the CPU to begin executing that program file starting at its beginning.
The operating system has a loader, whose job is to load the disc-based program file into memory of the process.
The loader knows about certain executable file formats.  Different operating system have different loaders and most likely understand different executable formats.
Machine code is contained in these program files, stored on disc using those file formats.  There are other ways to load machine code into memory, though a program file stored on disc loaded by the loader is the most common approach.
Asm, .asm, is a text file, human readable, for storing program code in assembly language.  To use it, such text file is given as input to a build system, which converts that human readable program code into a program file containing equivalent machine code, for later loading into a process by the operating system.
Not only do different operating systems support different file formats for program files, they also support different ways to interact with the operating system, which goes to their programming model that is described by an Application Binary Interface aka ABI.  All programs need to interact with the operating system for basic services like input, output, mouse, keyboard, etc..  Because ABIs differ between operating systems, the machine code in a program written for one operating system won't necessarily run on a different operating system, even if the processor is exactly the same.
Most disc-based file formats for executable program files contain indicators telling what processor the program will run on, so the same operating system on different processors requires different machine code, and hence usually different executable program files.  (Some file formats support "fat" binaries meaning that the machine code for several different processors is in one program file.)
Operating systems also have features that allow execution of new machine code within an existing process.  That machine code can be generated on the fly as with JTT compilers, or loaded more informally by an application program rather than the operating system loader.  Further, most operating system loaders support dynamically loading additional program file content from executable program files.
So, there's lots of ways to get machine code into the memory of a process for execution — support for machine code is one of the fundamental features of operating systems.
Let's also note that no real program is pure machine code — programs use machine code & data together, so all executable file formats store both machine code and data (and metadata).

Is there way to ignore not-found system function in a kernel .sys module? so to run .sys in older Windows

I'm facing such a problem. I've built a Windows kernel mode driver using WDK11, and, in order to pass Windows 11 WHQL, I need to use new memory allocating function ExAllocatePool2. The problem is, this driver will fail to load on Windows 7.
You know, Win7 does not have ExAllocatePool2, just like a user-mode EXE cannot find a new-era API in a system DLL on an older Windows OS, so the EXE fails to run.
For a user mode EXE, I can use LoadLibrary and GetProcAddress trick to dynamically detect that new-era API is not available at runtime, so that I can fall back to call older API.
I think the same idea applies to kernel mode, using RtlIsNtDdiVersionAvailable to probe for OS version, then call best available API from the system. But how to do real runtime dynamic linking to desired API?
Or, if there is a way to tell the system to ignore ExAllocatePool2 resolving errors when loading my .sys, the question is considered resolved as well.
In one word, the requirement is, I want to have a single binary to support all of Win11/Win10/Win7, and use new APIs on new OS.

How is an efi application being set as the bootloader through code?

By following this tutorial, I am able to create a simple efi application that prints hello world when executed from an uefi shell. However, I was wondering how does one creates bootable EFI image. I tried to use bcfg command in the shell and added my efi binary as one of the booting sequence. However, is there anyway to do it without the need of going into the shell?
However, if you are actually building your own firmware, you can also
look at creating a bootable EFI image and set your default boot option
to this binary. This is most useful if you are including the binary as
a part of your ROM, but it might be a little involved to set up the
filesystem so that it is seen as a normal boot option.
In this question, Nicholas Embry gave a good answer but I was unable to find any resource to explore further into the topic that he mentioned. Any help would be appreciated. Thanks!
bcfg, just like efibootmgr in Linux, ultimately use the GetVariable() and SetVariable() runtime services (also available during boottime) to modify the system boot configuration.
The UEFI Shell, implementing the bcfg command, is itself a UEFI application. Since its source is publicly available, you can have a look at the implementation of the bcfg command - particularly the BcfgAdd() function.
Adding on to unixsmurf's answer, I figured that it is in the specification that UEFI will automatically look for a file name/located at EFI/BOOT/bootx64.efi. When making a UEFI application that is intended to be automatically loaded by the machine when booting, simply place the application at the specified path. Combining with what unixsmurf mentioned, I can make the computer load any UEFI application automatically at boot time.

How BIOS boot from floppy and CD-ROM differently?

My test OS boots from floppy before, now I am trying to boot it from CD-ROM. But I am not quite sure how BIOS treat the floppy boot sector and CD boot sector differently. It seems the CD boot sector is much bigger than floppy boot sector. Is there any other things I need to notice?
Could anyone elabrate the details about it or point me to some links?
Thanks.
I would recommend booting with GRUB. Use the eltorito image to make the CD bootable. Then include your kernel in the CD image and make an entry in the GRUB configuration file use your kernel file like: kernel mykernel
Include any initrd if you have and boot.
To know about CD boot sectors i would tell you to have a look to the ISO Specifications
Wikipedia link
The ISO 9660 File System
ISO9660 Simplified for DOS/Windows
OSDev Link
I hope these links would help
To start, you should know that the bios does not use sector one of the CDrom to boot but sector 17 if I remember right.
You can learn alot by looking at the cdrom boot files which bootloaders such as grub or lilo use. Maby even minix has a cdboot option.

How do I setup an init.d rc script for a Daemon-kit project?

I am using the Ruby Daemon-kit to setup a services that does various background operations for my Rails application.
It works fine when I call in on the commandline:
./bin/bgservice
How do I go about creating a daemon initd starter script for it, so that it will autostart on reboot?
There's a few approaches:
You could write /etc/init.d/ scripts that could be placed into the /etc/rc?.d/ directories (or wherever they live on your target distributions). Some details on this mechanism can be found in the Debian policy guidelines and openSUSE initscript tutorial. There's an annoying number of distribution-specific idiosyncrasies in initscripts, so don't feel about writing a simple one and asking distributions to contribute 'better' ones tailored for their environment. (For example, any Debian-derived distribution will provide the immensely useful start-stop-daemon(8) helper, but it is sorely missing from other distributions.)
You could write upstart job specifications for the distributions that support upstart (which I think is Ubuntu, Google ChromeOS, Fedora, .. more?). upstart documentation is still pretty weak, but there are some details and plenty of examples in /etc/init/ on Ubuntu, probably the same location in other distributions that use upstart. Getting the dependencies correct may be some work across all distributions, but upstart job specifications look far simpler to write and maintain than initscripts.
You could add lines to /etc/inittab on distributions that still support the standard SysV-init inittab(5) file. This would only be useful if your program doesn't do the usual daemon fork(2)/setsid(2)/fork(2) incantation, as init uses the pid it gets from fork(2) to determine if your program needs to be restarted.
Modern Vixie cron(8) supports a #reboot specifier in crontab(5) files. This can be used both by the system crontab as well as user crontabs, which might be nice if you just want to run the program as your usual login account.
As the author of daemon-kit I've avoided making any init-style scripts due to coping with the various distributions and they're migrations from old init-V style to newer upstart/insserv, saving myself a nightmare.
How I recommend to do this is to use the god config-generator, and ensure god is started on boot (by runit or some other means), and god starts the daemon up initially and keeps it running.
At best I'll expand daemon-kit to be able to generate runit scripts for boot...
HTH.