U3 (UEFI implementation for some arm and mips boards)
Posted: Wed Mar 29, 2017 5:08 pm
Ok, since the work tonight is not working out, I've finally decided to write some short "announce" here. It's not really an announce, since there are no samples of the project doing much yet, but the code can already run on the hardware in question (mips machine) and it slowly is getting more functionality, so I put this topic, so that I will have a place to report progress or something, have answers and questions (probably), take advices, even overly lengthy. anything related.
It's a sub-project of my OS project and it's about creating a UEFI compliant implementation for a couple of arm and mips boards.
it's not based on Tianocore. I am creating it for educational purposes, to learn and test myself on ability to program HW. And, maybe it would be useful for others for the same reasons or even for the direct usage as a FW.
The target boards chosen are:
Mips Creator CI20 - mips32r2
Beagle Bone Black - armv7 (aarch32)
Cubieboard 2 - armv7 (aarch32)
Pine64+ - armv8 (aarch64)
Some settop box with RK3368 - armv8 (aarch64)
Only mips32 and aarch32 are somewhat touched by the project so far, aarch64 is not yet.
The project informally is called U3 as a shortening of uefi.upptech.ua - where "upptech" is a non-registered "organization" consisting of me as a developer. The OS is called ANT (and finally, its POSIX environment subsystem is called PussyX as my signature shows).
The implementation has its main goal as to be a UEFI-conformant firmware for a few SBC. Those don't have it yet. So, there is a practical goal too, to bring UEFI support into the (mostly arm) SBC landscape.
It does follow the PI spec as well, but it's not a strict requirement, it's an internal implementation thing anyway, UEFI is the standard implemented. So for example it is split up into PI defined phases:
- SEC ("teh security", taking control of ROM code, a very basic initialization in fact)
- PEI (pre Efi init - SDRAM init mostly)
- DXE (driver execution environment, everything goes here, it's a UEFI "kernel", exactly it supplies UEFI Services for example)
- BDS (boot device selection, UEFI Boot Manager, dealing with boot policies, boot options, interaction with user)
we kind of follow this. But the Pei phase is omitted on the mips target. And will be omitted on armv7 targets too. There are reasons for this - it avoids unnecessary duplication between Dxe and Pei. We put Pei's responsibilty of inintializing SDRAM on the Sec blob, and everything else is done by Dxe. You will not be wondered to hear, that some EDK targets also omit the Pei phase. It doesn't look sane to do this split (between Pei and Dxe) on SoC based designs. Pei foundation has a very similar tasks and organization to the Dxe counterpart, still it differs and results in duplication. I mean PPI vs Protocols, PPI database vs Handle Table, PEIMs dispatching vs DXE drivers dispatching. Basically Pei has been invented as a little Dxe, for platforms where it's needed. Or for additional solidity, some other reasons. SoC based machines clearly will be happy with this phase fusion.
Mostly we are at the Sec stage. Some portions of UEFI services are written as well, but not tested yet. Handle table database (with protocols of course) organization is designed.
The Sec blob, SEC.SYS is written entirely in assembly - I said I want to learn HW programming. It's a format-less binary which is put where the ROM code expects it to be, for the SD card boot scenario (that we are using now), it's right after an MBR sector. Fortunately, the first partition lies so far away from this area, we can easily fit our entire FW into this spare area, not messing up with partitions. But this scenario is a beginning one. We need more permanent storage where it's present (not always it's the case on the SBC landscape, examples - Pine64+, our aarch64 target, Raspberry Pi, they don't have eMMC or NAND storages, only SD card slots) to store our FW. So with the progress, we migrate to NAND for the CI20 target.
Our SEC gets loaded by the ROM code into TCSM - tightly coupled shared memory, a SRAM area with only 14 KB of available space (this limitation was an initial reason we offcast the PEI phase).
So far SEC.SYS only can print into UART, starts PLLs and configures clocks for the CPU, L2 cache, AHB0 and AHB2 buses and for PCLK - peripheral clock, also it initializes the OS Timer. It plays with the LED, and has some support routines for printing.
Now we need to finally initialize SDRAM. Then configure SD controller and read our Dxe.exe PE file into SDRAM and load it as an executable. Then create HOB-list (jack off, sorry, - hand off blocks - needed for memory representation for Dxe) and jump to DxeEntryPoint(). Later, when we figure out what the security it really needs, we add it here, so far, practically, it's a fancy 1st stage bootloader for the rest of FW, if you want, but with an SDRAM initialization bonus inside.
It's a sub-project of my OS project and it's about creating a UEFI compliant implementation for a couple of arm and mips boards.
it's not based on Tianocore. I am creating it for educational purposes, to learn and test myself on ability to program HW. And, maybe it would be useful for others for the same reasons or even for the direct usage as a FW.
The target boards chosen are:
Mips Creator CI20 - mips32r2
Beagle Bone Black - armv7 (aarch32)
Cubieboard 2 - armv7 (aarch32)
Pine64+ - armv8 (aarch64)
Some settop box with RK3368 - armv8 (aarch64)
Only mips32 and aarch32 are somewhat touched by the project so far, aarch64 is not yet.
The project informally is called U3 as a shortening of uefi.upptech.ua - where "upptech" is a non-registered "organization" consisting of me as a developer. The OS is called ANT (and finally, its POSIX environment subsystem is called PussyX as my signature shows).
The implementation has its main goal as to be a UEFI-conformant firmware for a few SBC. Those don't have it yet. So, there is a practical goal too, to bring UEFI support into the (mostly arm) SBC landscape.
It does follow the PI spec as well, but it's not a strict requirement, it's an internal implementation thing anyway, UEFI is the standard implemented. So for example it is split up into PI defined phases:
- SEC ("teh security", taking control of ROM code, a very basic initialization in fact)
- PEI (pre Efi init - SDRAM init mostly)
- DXE (driver execution environment, everything goes here, it's a UEFI "kernel", exactly it supplies UEFI Services for example)
- BDS (boot device selection, UEFI Boot Manager, dealing with boot policies, boot options, interaction with user)
we kind of follow this. But the Pei phase is omitted on the mips target. And will be omitted on armv7 targets too. There are reasons for this - it avoids unnecessary duplication between Dxe and Pei. We put Pei's responsibilty of inintializing SDRAM on the Sec blob, and everything else is done by Dxe. You will not be wondered to hear, that some EDK targets also omit the Pei phase. It doesn't look sane to do this split (between Pei and Dxe) on SoC based designs. Pei foundation has a very similar tasks and organization to the Dxe counterpart, still it differs and results in duplication. I mean PPI vs Protocols, PPI database vs Handle Table, PEIMs dispatching vs DXE drivers dispatching. Basically Pei has been invented as a little Dxe, for platforms where it's needed. Or for additional solidity, some other reasons. SoC based machines clearly will be happy with this phase fusion.
Mostly we are at the Sec stage. Some portions of UEFI services are written as well, but not tested yet. Handle table database (with protocols of course) organization is designed.
The Sec blob, SEC.SYS is written entirely in assembly - I said I want to learn HW programming. It's a format-less binary which is put where the ROM code expects it to be, for the SD card boot scenario (that we are using now), it's right after an MBR sector. Fortunately, the first partition lies so far away from this area, we can easily fit our entire FW into this spare area, not messing up with partitions. But this scenario is a beginning one. We need more permanent storage where it's present (not always it's the case on the SBC landscape, examples - Pine64+, our aarch64 target, Raspberry Pi, they don't have eMMC or NAND storages, only SD card slots) to store our FW. So with the progress, we migrate to NAND for the CI20 target.
Our SEC gets loaded by the ROM code into TCSM - tightly coupled shared memory, a SRAM area with only 14 KB of available space (this limitation was an initial reason we offcast the PEI phase).
So far SEC.SYS only can print into UART, starts PLLs and configures clocks for the CPU, L2 cache, AHB0 and AHB2 buses and for PCLK - peripheral clock, also it initializes the OS Timer. It plays with the LED, and has some support routines for printing.
Now we need to finally initialize SDRAM. Then configure SD controller and read our Dxe.exe PE file into SDRAM and load it as an executable. Then create HOB-list (jack off, sorry, - hand off blocks - needed for memory representation for Dxe) and jump to DxeEntryPoint(). Later, when we figure out what the security it really needs, we add it here, so far, practically, it's a fancy 1st stage bootloader for the rest of FW, if you want, but with an SDRAM initialization bonus inside.