UEFI Secure Boot Linux Permissions - linux

I've got a CentOS setup with UEFI Secure Boot turned on. I'm working on debugging a set of BIOS tools that were developed quite some time ago. However when Secure Boot is turned on it appears user applications are not allow to get higher privilege levels any more.
Essentially I have a kernel module that maps a virtual to physical memory buffer which is used to communicate to the BIOS. The buffer is setup and a software SMI is called so the BIOS can retrieve it, process it, and put the results back into the buffer.
I'm trying to figure out how this can still be done with Secure Boot enabled? The kernel module can still setup the buffer, but it appears like I'm unable to call into my character device setup by the kernel module.
Any ideas?

Related

UEFI Memory location

I am attempting to write an x86_64 PC emulator. I was wondering in what memory location the UEFI is mapped. I know that a BIOS is usually mapped from 0xf0000-0xfffff and 0xf0000000-0xffffffff. Is UEFI mapped to the same locations?
Yes, the UEFI firmware is loaded to the same locations as well as legacy BIOS. Otherwise, why is cs:ip is pointing 0xFFFFFFF0 in its initial state?
Check out the OvmfPkg in EDK II. This is an open-source UEFI firmware for virtual machines. You can load it into famous emulators like Bochs, QEMU.
You can also use VMware's EFI firmware, but in that it is proprietary, you might want to read VMware's license before you really want to proceed with it.
UEFI is not loaded in a specific memory location. Something needs to be placed where the processor starts fetching instructions, and then SEC and PEI stages prepare for DXE to be uncompressed somewhere dynamically - loading individual PE/COFF as it goes.
The way you find out what memory regions are reserved is by calling the GetMemoryMap boot service at runtime.
You may find the documentation of the existing EDK2 virtual machine port helpful.

How early can I send data to a serial port on Linux boot?

I have an external serial peripheral that needs to be setup on Linux boot, on an embedded system.
What I need is sending a short configuration string as early as possible during system boot, so my procedure is simply
Set port to 115200 bps
Send a string, like "ABCDE\r\n"
I see that recent kernels support an early-on serial console, but what I need is not a console (my peripheral can also send meaningless data in that phase, plus I'll be showing a splash screen in graphic mode), just a fast initialization for the the peripheral.
How can it be done?
The answer to this will be subjective depending on what you mean by as early as possible. I will provide few possibilities I am aware of which might help you
In case your embedded platform uses any form of bootloader (ex: U-Boot) then you can do the serial(UART) initialization as part of the bootloader (Usually this will be done for the target platform alone so that we can see how far the boot is happening). You can try initializing your external serial peripheral in bootloader itself. As bootloader will execute before the linux kernel gets loaded you can achieve this easily.
If your platform doesn't use any form of bootloader then the possibility of initializing the external serial peripheral is via kernel driver (or) system init process.
I have been using PSplash program which uses the basic frame buffer driver for the boot progress. If interested check the following repo
PSplash

Automatically enabling all ethernet, ATA, SATA, and SCSI drivers in the Linux .config file

I am compiling my own Linux kernel and userland tools for a PXE environment meant for cloning and reimaging. Right now, I'm sticking to a specific kernel version and using preconfigured .config's for building the Linux kernel.
I need to change from using preconfigured .config's to automatically generating the default configuration for the specified architecture, and then enabling all ethernet, ATA, SATA, and SCSI drivers.
The reason I want to do this is:
Updating the kernel means updating the preconfigured .config's, which takes too much time to manually do. The way I'm doing it now is using menuconfig, enabling the options I need, and saving the resulting .config to my repository.
I know the kernel I'm building is missing some drivers because I've encountered some PC's that were not able to mount the NFS share because Linux could not find an ethernet device (which I've verified by booting an Ubuntu CD, which did find the ethernet device). I want an automated way of building any Linux kernel version that will guarantee that ALL drivers I need are pulled in.
Using a distribution's configuration pulls in too many unnecessary drivers and features for my purposes. It lengthens the kernel build time from 10-15 mintues to an hour or more, and the resulting image is too big.
Does anyone know how to write a Bash script to accomplish this?
Have you considered using a text editor to modify the .config file.
Then you can modify it using search and replace.
Plus, there are other choices for configuring the kernel than the menu-driven "menuconfig".

How can the linux kernel be forced to enumerate the PCI-e bus?

Linux kernel 2.6
I've got an fpga that is loaded over GPIO connected to a development board running linux.
The fpga will transmit and receive data over the pci-express bus. However, this is enumerated
at boot and as such, no link is discovered (because the fpga is not loaded at boot).
How can I force re-enumeration of the pci-e bus in linux?
Is there a simple command or will I have to make kernel changes?
I need the capability to hotplug pcie devices.
As root, try the following command:
echo "1" > /sys/bus/pci/rescan
See this link for more information: http://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci
I wonder what platform you are on: A work around (aka hack) for this that works on x86 systems is to have the BIOS basically statically configure a PCI device at whatever bus, device, function the FPGA normally lands on, then the OS will enumerate the device and reserve the PCI space for it (even though the device isn't really there). Then in your device driver you will have to do some extra things like setup the BARs and int lines manually after the fpga has been programmed. Of course this requires modifying the BIOS, which if you are working with a BIOS vendor you can contract them to make this change for you, if you are not working with a BIOS vendor then it will be much harder... Also keep in mind that I was working on VxWorks on x86, and we had a AMI make a custom BIOS for our boards...
If you don't have a BIOS, then consider programming it in the bootloader, there you already have the ability to read from disk, and adding GPIO capabilities probably isn't too difficult (assuming you are using jtag and GPIOs?), in fact depending on what bootloader you use it might already be able to do GPIO?
The issues with modifying the kernel to do this is that you have to find the sweet spot where you can read the bitfile, before the PCI enumeration... If for example the disk device drivers are initialized after PCI, then obviously you must do some radical changes to the kernel just to read the bitfile prior to PCI enumeration, which might cause other annoying problems...
One other option which you may have already discovered, and which is really only ok for development time: Power up the system, program the fpga board, then do a reset (without power cycle, for example: sudo reboot now), the FPGA should keep its configuration, and linux should enumerate it...
After turning on your computer, the BIOS enumerates the PCI bus and attempts to fulfill all IO space and memory mapped IO (MMIO) requests. It sets up these BAR's initially, and when the operating system loads these BAR's can be changed by the OS as it sees fit while the PCI bus driver enumerates the bus yet again. It is even possible for the superuser of the system to run the command setpci to change these BAR's after the BIOS has already attempted to configure them and the OS has loaded (may cause drivers to fail and several other bad things if done improperly).
I have had to do this in cases where the card in question was not assigned any resources by the BIOS since the region requested required a 64-bit address and the BIOS only operated with 32-bit address assignments. I was able to go in after-the-fact and change these addresses (originally assigned by the BIOS) to whatever addresses I saw fit, insert the kernel module, and my driver would map and use these newly-assigned addresses for the card without knowing the difference.
The problem that exists with hotplugging PCI-Express cards is that the power to the slot, itself, cannot be turned on/off without specific hotplug controllers that need to exist on the motherboard/backplane. Not having these hotplug controllers to turn the slot's power off may lead to shorts between the tiny pins when the card is physically inserted and/or removed if power is still present. Hotplug events, however, can be initiated by either end (the host or the endpoint device). This does not seem to be the case, however if your FPGA already has a link established with the root complex, a possible solution to your problem would be to generate hotplug interrupts to cause a bus rescan in the OS.
There is a major problem, though -- if your card does not actually obtain a link to the root complex, it won't be able to generate any hotplug events; which seems to be the case. After booting, the FPGA should toggle the PRESENT line on the PCIe bus to tell the OS there is a card ready to be enumerated. Once detected, the OS should attempt to establish a link to the card and assign memory regions to the device. After the OS enumerates the card you'll be able to load drivers against it and see it in lspci. You stated you're using kernel 2.6, which does have support for hotplugging and dynamic resource allocation so this method should work as long as your FPGA supports the ability to toggle the PRESENT PCIe line, too.

Is there a way to ask the Linux Kernel to re-run its PCI initialization code?

I'm looking for either a kernel mode call that I can make from a driver, a userland utility, or a system call that will ask the Kernel to look at the PCI bus and either completely re-run its initialization, or initialize a specific device. Specifically, I need the Kernel to recognize a device that was added to the bus after boot and then configure its address space, interrupt, and other configuration parameters, and finally enable the device so that I can load the driver for it (unless this all happens as part of the driver load).
I'm stuck on the 2.4.x series Kernel for this, and am currently working with 2.4.20, but will be moving to 2.4.37 if it matters. The distro is a stripped down Red Hat 7.3 running in a ram disk, but I can add in whatever tools are needed to get this working (as long as they play nice with 2.4 series).
If some background would help clarify what I'm trying to do: From a cold boot, once in Linux I use GPIO to program an FPGA. Part of the FPGA, once programmed, implements a simple PCI device. Currently, after programming the FPGA, I reboot the system and Linux recognizes the device after coming up and loads the driver for it.
Instead of needing that reboot, I'd like to simply ask the Kernel to do whatever it does during boot up to find PCI devices (I have the Kernel configured to find PCI devices on its own, instead of asking the BIOS for that information, so the BIOS won't need to know about this device (I hope)).
I believe that Linux is capable of seeing the device after it is programmed but before a reboot, because scanpci will show the device after I program it, as will lspci -H 1. I just need a way to get it into /proc/pci, configured and enabled.
This below command will help the user to rescan it complete root hub.
echo "1" > /sys/class/pci_bus/0000\:00/rescan
You could speed up the reboot with kexec, if you don't figure out how to get the PCI scan redone. You could ask this on the LKML, if you haven't already.
unloading/reloading the module doesn't help, does it?
http://www.linuxjournal.com/article/5633 suggests you should be able to do it with 2.4 kernels using pcihpfs.
If that isn't working, maybe the driver doesn't support hotplug?
It would probably crash the system if you reconfigured the addresses of other PCI devices while they are in use.
A better way would be to just configure the new card. If your kernel has support for Cardus devices, it already knows how to configure a newly-inserted PCI device (which is what Cardbus is). You just need to figure out how to get the kernel to do it...
It should be possible for a kernel module to do this. Even if you can't get built-in hotplug code, you should be able to set the pci resources using calls to pci_bus_write_config_dword() and friends. There is probably some IRQ routing setup to do as well.

Resources