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

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.

Related

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.

At what point in the boot process are systemd generators run?

The systemd.generator man page says that generators are run very early at bootup and that they are all run at the same time. At what point in the bootup are they actually run?
As I understand it, CoreOS's ignition is implemented as a generator which runs after the initramfs is mounted but before pivoting to the root filesystem, is this a CoreOS specific thing or is this common to any OS using systemd init?
At what point in the bootup are they actually run?
They run every time the systemd-pid1 manager is started: https://github.com/systemd/systemd/blob/v235/src/core/manager.c#L1333
In practice, this means either as one of the very first steps when pid1 is executed or after a daemon-reload. The latter also includes the transition between initramfs and the real rootfs.
ignition is implemented as a generator
Ignition is not implemented as generator, but as a first-boot initramfs service. If you read any doc page stating that ignition is a systemd generator, please report a bug against that as it is incorrect.
is this a CoreOS specific thing or is this common to any OS using systemd init?
Ignition is a CoreOS specific component. It is open-source and can be ported to any systemd-based distribution, but I am not aware of any other distribution using it. See https://github.com/coreos/ignition

Running an EFI application automatically on boot

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

memory command is not available even after compiled with TCL_MEM_DEBUG flag

I have memory related problem in my application on solaris9 environment where Tcl_DeleteInterp() function calls lot of free() and mutex_unlock() functions. To debug the problem i followed the below steps to compile tcl on solaris server (with TCL_MEM_DEBUG flag) but still i couldn't use the 'memory' command in my interpreter.
Ran configure script on server (./configure –prefix=<directory needs to be installed> --enable-symbols=mem)
Make clean all
Make install (tcl libraries and tlcsh exe is copied to the path specified in step1)
Compilation generated two libraries (libtcl8.4g.so and libtclstub8.4g.a), I copied libtcl8.4g.so as libtcl8.4.so to my app
Copied tcl8.4 directory as well.
I also copied the tclsh8.4 to $PROVHOME/bin and created soft link as tclsh-> tclsh8.4.
From my application i linked the debug symbol enabled libraries to the place where exactly i created the Tcl interpreter.
Initialized the Tcl interpreter to using Tcl_InitMemory() function (so that the memory command will be registered in the supplied(arg) interpreter.
When i used the interpreter exe (tclsh) separately i could execute the memory command, but when i used the same exe on my application its not working. Can someone help me what could be the possible reason for this problem ?
Also help me how can i cross verify the libraries that they are compiled with TCL_MEM_DEBUG flag.
Will the Tcl source code tar file contain Solaris directory where i have to build the libraries or should i use the unix source code for solaris platform as well ?
Thanks
Are you using [mem] interactively (which does expansion of unambiguous short command names) and forgetting to use the full name ([memory]) in your scripts?
You're using Tcl embedded in your code? You need to call Tcl_InitMemory (passing in the handle to the interpreter where you want the memory command created) after creation of the interpreter and before you run user scripts, i.e., straight after the Tcl_CreateInterp gives you the handle (which should in turn come after the Tcl_FindExecutable call that initializes the shared parts of the library).
You must also make sure that everything is built with that flag set so that the correct memory allocation APIs are used in both your code when it integrates with Tcl, and you must make sure that you are linking against the debugging build. It's probably the linking that has gone wrong, but I've not done that level of development on Solaris for many years.
I think you'll find that “Getting a list of used libraries by a running process (unix)” is relevant to your problems.

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.