User:Microfool/Draft:U-Boot4PAZ00
According to rules, I must put Dogfooging tag, but I am sure is it relevant.
| π§ | This page is a work-in-progress. Some information contained within may be inaccurate or incomplete. |
U-Boot for PAZ00: Porting & Feature Implementation and Reverse Engineering
This is a landing page for a project focused on porting and implementing features of Mainline U-Boot to Nvidia Tegra platforms. Here we can see the progress and problems along the way. (First and foremost, this covers the Tegra2 PAZ00 / AC100 Toshiba.)
Goals
Currently, the status of the working U-Boot implementation by the community is nearly complete β approximately 90% of the functionality that can be built and run on the Tegra platform is working. Our task is to finish and test the remaining functionality that has been declared but does not work, is missing, or builds but runs with errors.
We will be posting news here about functionality improvements and feature implementations.
Another goal is to keep and share the results of research and reverse engineering I perform.
Today I work with my own repository, but I have not published many patches publicly; mostly I work on a local repository, and I have a mess with branches.
https://github.com/ZalgoSoft/u-boot
Functionality Known Not to Work
1. ebtupdate command
The command builds but requires tegra_aes. In the device tree (DTC), the hardware AES devices are disabled: these are the audio and video stream processors. There are two of them:
compatible = "nvidia,tegra20-bsev";compatible = "nvidia,tegra20-bsea";
It is unknown whether they provide sufficient functionality for AES. When enabled, the tegra_aes driver attaches to them, but executing ebtupdate ends with a segfault crash in svc32 at the moment of accessing IRAM.
TODO: Enable these devices in DTC by default, implement full support for the Tegra crypto device.
2. ums command
Requires setting the first USB controller to UDC mode in the device tree. It builds and runs, but only once. Upon the first termination, it corrupts the tegra-udc driver structure, after which a second run fails to produce a USB gadget mass storage result.
TODO: Enable mode=otg in DTC, investigate USB structure corruption.
3. EFI runtime services
Disabled by default. There are only two of them β set time and get time. They work but produce incorrect results.
TODO: Fix EFI interaction with RTC.
Working with NVEC
Currently, support for the Nvidia NVEC device is rudimentary and works with errors. In particular:
- I2C timings are not respected when working with the keyboard, making it impossible to type with modifier keys like Shift, or capital letters are printed randomly every 10th time.
- There is no support for other devices within the NVEC subsystem: LEDs, battery, sensors, touchpad/PS2. Additional functionality may also be present, such as working with EC SPI EEPROM or EC debugging. Support for these is not mandatory, but once started, it is hard to stop.
Existing Implementations
There are existing implementations of similar devices in the codebase:
CROS_ECβ its protocol is very similar and much more advanced. The difference is that the device does not operate in I2C slave mode.DesignWare MFDβ very similar, but it is unclear whether the implementation quality is good or if it is also a workaround.- Mainline Linux Kernel NVEC source code β well-developed code that works without obvious errors, considering the hardware limitations of the device. It still has a staged status.
Challenges
The CROS_EC and Linux options are complex because the algorithm uses a workqueue. The implementation for NVEC is complex because the device operates in I2C slave mode.
There is no good implementation of tegra_i2c, including for slave mode. The code is fragmented and poorly compatible with other drivers of this class. Tegra U-Boot has no devices that rely on I2C and it is not critical for booting, so its functionality is questionable.
Chipidea USB Gadget Driver Model
There is no support for DM CI (Driver Model Chipidea). As a result, modern gadget functionality does not work.
TODO: Write logic from scratch, using existing routines.
Ethernet USB Gadget Functionality
It should be possible to run PXE boot out of the box using an available method, specifically via USB OTG mode, EDC, or RNDIS. Currently, the driver does not start.
TODO: Investigate buggy behaviour, apply patches.
Flat Image Tree (FIT)
Even not tried to work. Nor binman customization. This is a fresh way to deploy U-Boot binaries stick with kernel and related to EFI support.
Falcon Boot
Even not tried. Will require changes to the SPL part. It is somehow related to FIT. No fit β no shit.
FDT or FIT Overlays
By default no support for DTB overlays. May enable this at no cost.
Verified Boot / Secure Boot
It would be interesting to implement emulation for Secure Boot. This would require emulation of a hardware encryption device or some kind of TPM. For now I cannot find EFI tools to work with MOK and key storage which are able to run on ARM32. Anyway useless and barely real.
NVRAM Emulation
Currently there is support for U-Boot variables storage on MMC and EFI variables in a file on the EFI partition. There is a lack of write access to the EFI store and runtime service. Linux drivers require an NVRAM device.
We have enough space on mmcblk0boot1 to keep any data we need to store, to emulate CMOS BIOS, and to propose this capability to EFI, especially in Runtime Mode, access from OS, etc.
TODO: Add and change some code. It should not be too hard.
PSTORE Support and EFI
Even though it is enabled and supported by Linux Kernel, it is not too clear how it should work. I was not able to mount pstore or efi_pstore from Linux and work with it.
This task is relevant to EFI runtimes. If efi_pstore works, we could be able to access EFI variables from runtime.
TODO: Clarify the way to work with pstore.
BIOS Setup Menu
I have a dream: have my very own BIOS menu. Now U-Boot is capable of this, but in a special way: the CEDIT menu system, whose data can be kept in a DTC overlay. We must develop a unified structure for option elements and values, which could be used in other parts of U-Boot. E.g.: boot order, boot menu, splash image, boot devices, recovery case.
Another way is to create an EFI Setup runtime. Such examples can be found on Raspberry Pi or even on older Tegra models.
TODO: I will try both ways.
Wi-Fi Functionality
In reality, U-Boot has no official support for 802.11, much like most PXE/iPXE implementations. It would require implementing wpa_supplicant and crypto libraries.
TODO: Not to be done.
Fastboot
Not able to run. Lack of USB support or something.
EFI Implementation
It would be awesome to run its own full stack EFI with PEIM, but this is not a task of U-Boot. There are projects for older Tegra models, but it seems nobody has built them for Tegra ARM32.
Today's status: some apps can be run: EFI Shell, EFI GRUB.
TODO: Hmmm. Never.
Slow MMC Read During EFI Boot
Every few milliseconds, a keyboard survey executes, which slows IO operations to 20β40 seconds reading the kernel. Another side effect is slowdown of U-Boot timers, which affects, for example, the countdown timer menu.
A workaround for this is the patch:
https://github.com/u-boot/u-boot/commit/0c1cbbbe54437b9ed342026cdc691152da7099b4
Not too much β it is temporary, while implementing NVEC support.
My Research
Tools
Tool to extract BMP images from stock bootloaders of any Tegra.
KGDB for ARM
Implemented and successfully ran debugging with GDB and VS Code via Serial line.
It is a huge patch which will barely be accepted into Mainline U-Boot. I still do not know how far I should apply it β I mean, limit to only one device (paz00) or expand to the mach-tegra family or even to the entire arch/arm branch.
No code still published.
Bootflow Menu Layout Corruption
Wrote a patch for bootflow menu to respect console size. Published.
Bootflow Menu works closely with the CEDIT component, taking some settings from its part, e.g., theming. Needs further investigation.
EFI Boot
Ran EFI boot for some distros, like Fedora, OpenSUSE, Ubuntu 22.04. Will write RTFM.
Runs out of the box, no need for special tricks. Run from EFI Shell, run from EFI-GRUB, run directly from U-Boot, even from U-Boot EFILINUX sysboot.
The only issue is to find the correct DTB which is fully accepted by the Linux Kernel. For example, some kernels do not take OOPS settings (power management and scaling) from DTB, e.g., Ubuntu 22.04, Ubuntu 24.04 even with their stock DTBs. Even more, Ubuntu 24.04 runs only under special circumstances β from its own distro's U-Boot, seems to have some special settings about memory mapping, DTB and initrd storing or something.
Improved NVEC Driver Code
Enhanced code and applied to main. Still in development.
Some Features Built into My U-Boot Variant
UMS
ums 0 mmc 0
Works only the first time. Other times no Mass Storage is exposed. Seems to be somehow broken with the ChipIdea gadget driver. It corrupts USB driver inner structures.
DFU
Successfully run and reproducible. Need to correctly set the dfu_alt_info variable:
setenv dfu_alt_info mmc raw 0 0x1f0000000
USB CDC Terminal
Works poorly. When enabled with:
setenv stdin usb_cdc setenv stdout usb_cdc setenv stderr usb_cdc
may go to segfault and freeze. Need to find the right way to run it 100% of the time.
EFI Menu
Successfully run and reproducible. Commands to work with: eficonfig, efidebug, bootmenu -f, bootefi bootmgr.
Need to clarify how to set bootargs or cmdline to pass into the Linux kernel. Does not work for some kernels.
Peripheral Commands
Commands like rtc, pmic, i2c, gpio, pwm, timer, spi, enhanced mmc, usb gadget, DM model standard boot, sysboot. Still not published.
Some of them cannot access peripheral hardware even with Tegra drivers enabled, some corrupt driver data, some have no special Tegra device support.
KB926D EC
Moved here from the AC100 page.
This part contains research and may not be fully trusted.
POST Messages
Getting Debug Messages from EC
To receive debug messages from the EC, connect to the EC_TX80_PDATA output and set the baud rate to 115200. EC_RX80_PDATA is not routed on the board, and its functionality is unknown.
The following messages from the EC controller have become available:
Without a Battery
Connecting the board's power cable, transitioning to the OFF state
The power LED lights up, messages ppL appear, followed by 00,FLASHDEEP with a periodicity of 1 second:
DEEP00,FLASHDEEP00,FLASHDEEP00,FLASHDEEP00,FLASHDEEP00,FLASHDEEP00,FLASHDEEP00,FLASHDEEP00,FLASHDEEP00,FLASHDEEP00,FLASHDEEP00,FLASHDEEP00,FLASH
Pressing the Power button, transitioning from the OFF state
The following messages appear:
ON01,PMUSD o01,E0,F0,PMUSD N0N1PMUSD @REQ=1 N2N3SD0C,ppL
Pressing Ctrl + Esc + Power, transitioning from OFF to APX (Recovery)
ON01,RN0PMUSD o01,E0,F0,PMUSD N0N1PMUSD @REQ=1 N2N3SD0C,`pL
Disconnecting the power cable, transitioning from ON to unpowered
3SD0C (sometimes followed by ,p`L)
In the ON state, when the SYSTEM_RESET# signal is applied
Nothing happens.
Connecting the battery while the power cable is connected
Nothing happens.
With a Battery
Cable plug in, transitioning from unpowered to OFF
00L or 00l or 00,.
Long pressing Power, transitioning from ON to OFF
SD13,F0,F1
Transition from ON to STANDBY / SUSPEND TO RAM
TBD
EC KB926D disassembled
https://github.com/ZalgoSoft/flash-kernel-paz00/blob/main/EN25F20.BIN.c
Most interesting there are protocols for some i2c enpoints - keyboard, ec, ps2, power, fan, leds. Need time to complete format desctioptions.
TX80_DATA messages revealed from source code. There routines with related names, where described logic of printing char sequence. [hex] - means number in hex. List of functions related to letters:
ps2_process_command: \n[hex]S[hex]P[hex] ps2_write_cw: CW ps2_write_cr: [hex]I ps2_write_cmd: [hex]SH fan_state_machine: f3 F1 F0, N1@CR N2 N3 R FUN_CODE_0e5f: N0 acpi_ec_cmd_handler: E[hex][hex]\n\n thermal_print_error: ER[hex][hex][hex] pm_power_on: ON[hex] ps2_process_response: RPO[hex] pm_set_power_state: SD[hex] ec_main_task: NVB NVC print_newline: NV uart_print_hex_byte: [hex], acpi_ec_poll: T
So, we can say:
- any hex number followed by coma,
- F - related to fan control, on, off and reset.
- F1 - fan reset,
- N - power sequence for NVIDIA,
- ER - actual POST message,
- SD - power state management,
- NV - boot mode selection command (B -bootloader or C - consumer).
- R - recovery mode in some case
- S (somethime with P) - ps2 related
Still not found: PMU, @REQ=1, L, H, pp, o, DEEP, FLASH. Partially found @RC.
General Architecture
The KB926D EC functions as the central I/O controller of the laptop. It collects data from all peripherals and forwards it to the Tegra 2 via I2C.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β KB926D EC β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β POST β Init β Main Loop β {Keyboard, PS/2, Battery, LID, I2C} β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ I2C (EC_TX80_PDATA β UART Debug)
βββββββββββ
β Tegra 2 β
βββββββββββ
Functional Blocks
1. POST and Initialization (_POST_Init @ 0x11f6)
| What it does | How it works |
|---|---|
| Boot mode check | Reads pin 0xFF01 (normal 0x00 / bootloader 0xF0) |
| Memory clear | Clears internal RAM (0x00β0x7F) and external RAM (0xF400β0xF800) |
| GPIO configuration | Configures ports via 0xFCxx registers |
| UART initialization | Configures serial port for debugging |
| POST code output | FLASH C NV β FLASH B (Bootloader) |
POST codes on UART (EC_TX80_PDATA):
FLASH - Flash memory initialization B / C - Mode: Bootloader / Customer (Normal) NV - Non-Volatile memory check ER<dump> - Dump of 0xF54B area (24+16+8 bytes) RPO - PS/2 report
2. UART Debugging (EC_TX80_PDATA)
| Function | Purpose |
|---|---|
UART_PutChar |
Send a character |
UART_HexByte |
Output byte in HEX (e.g., 4C,)
|
UART_HexDump |
HEX dump with prefix |
UART_DumpMemory |
Dump 24+16+8 bytes from 0xF54B |
UART_PrintNV |
Output NV string |
Example output during normal boot:
FLASH C NV ER<48-byte dump> RPO
3. I2C Master (Communication with Tegra 2)
| Function | Purpose | Address |
|---|---|---|
I2C_Init |
I2C initialization | 0x2622 |
I2C_Enable |
Enable I2C master | 0x223d |
I2C_SetClock |
Set clock frequency (0x20) | 0x2251 |
I2C_SendData |
Send data to Tegra 2 | 0x1368 |
I2C_MasterTransfer |
Main I2C transaction | 0x86e5 |
I2C_IsReady |
Check bus readiness | 0x28ba |
I2C_Stop |
Generate STOP condition | 0x28ac |
I2C Registers:
| Address | Purpose |
|---|---|
| 0xFF93 | Control |
| 0xFF94 | Command (3 = START + transmit) |
| 0xFF98 | Number of bytes |
| 0xFF99 | Counter |
| 0xFF9A | Data (low byte) |
| 0xFF9B | Data (high byte) |
| 0xFF95 | Status |
4. Keyboard and PS/2
| Function | Purpose | Address |
|---|---|---|
Keyboard_ScanMatrix |
Scan keyboard matrix | 0x1ace |
Keyboard_ProcessKeys |
Process key presses | 0xb71f |
PS2_SendReport |
Send PS/2 report (RPO) |
0x1c97 |
PS2_Command |
Process PS/2 commands | 0x84fb |
How it works:
- Scans 4 matrix rows (
DAT_EXTMEM_f51f < 4) - Reads pin states via
CONCAT11 - Builds an array of pressed keys
- Sends report to Tegra 2 via I2C
5. Power Management
| Function | Purpose | Address |
|---|---|---|
Power_Management |
Main power logic | 0xc067 |
Power_Button_Handler |
Power button handling | 0xd05e |
LID_Switch_Handler |
Lid close sensor | 0x8aa7 |
Timer_Handler |
Timer handling | 0xc7c1 |
ACPI_Handler |
ACPI events | 0xde00 |
LID logic:
- Reads pin state via
DAT_EXTMEM_f51d & mask - When closed β backlight off
- When opened β backlight on
Workflow Diagram
Power On
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β _POST_Init (0x11f6) β
β βββ Check pin 0xFF01 β
β βββ Memory clear β
β βββ Set up GPIO, UART, I2C, SMBus β
β βββ Print POST-code "FLASH" β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β _MainLoop (0x1fa0) β
β βββ Print 'B' or 'C' β
β βββ Print "NV" β
β βββ Endless loop β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β POST β Init β Main Loop β {Keyboard, PS/2, Battery, LID, I2C}
βΌ I2C (EC_TX80_PDATA β UART Debug)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Main Loop (thunk_FUN_CODE_f1f3) β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Keyboard_ScanMatrix() βββΊ keyboard scan β β
β β I2C_Dispatch() ββββββββββΊ send data to Tegra 2 β β
β β PS2_SendReport() βββββββββΊ print "RPO" β β
β β Power_Management() βββββββΊ power management β β
β β LID_Switch_Handler() βββββΊ check lid state β β
β β SMBus_Transaction() ββββββΊ battery polling β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β βΌ (loop) β
β repeat β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ