Boot.efi Information

From AwkwardTV

Jump to: navigation, search

Contents

Overview

In general, EFI executables adhere to the PE / COFF format, the documentation for which is readily available online: Portable Executable / Common Object File Format Documentation

At a glance, Apple's boot.efi does not adhere to this standard, but upon closer examination, it turns out to be two separate PE files concatenated together along with a Mach-O FAT Binary headerr.

FAT Mach-O header

<lang c> struct fat_header { uint32_t magic; /* FAT_MAGIC */ uint32_t nfat_arch; /* number of structs that follow */ };

struct fat_arch { cpu_type_t cputype; /* cpu specifier (int) */ cpu_subtype_t cpusubtype; /* machine specifier (int) */ uint32_t offset; /* file offset to this object file */ uint32_t size; /* size of this object file */ uint32_t align; /* alignment as a power of 2 */ }; </lang>

AppleTV boot.efi

00000000h: B9 FA F1 0E 02 00 00 00 07 00 00 00 03 00 00 00 30 00 00 00 D8 3F 02 00 00 00 00 00 07 00 00 01 ; ¹úñ.............0...Ø?..........
00000020h: 03 00 00 00 08 40 02 00 28 4F 02 00 00 00 00 00                                                 ; .....@..(O......
Offset Data Purpose
0x00 B9 FA F1 0E EFI Fat Binary Magic 0x0EF1FAB9 (little-endian)
0x04 02 00 00 00 Number of Architectures
0x08 07 00 00 00 First architecture record, 7 = CPU_TYPE_X86
0x0B 03 00 00 00 CPU subtype, 3 = CPU_SUBTYPE_I386_ALL
0xF0 30 00 00 00 Offset (in bytes) to beginning of first executable's header ( = 48 dec)
0xF4 D8 3F 02 00 Length (in bytes) of first executable ( = 147416 dec)
0xF8 00 00 00 00 Alignment (i386 does not require alignment)
0xFB 07 00 00 01 Second architecture record = CPU_TYPE_X86_64
0x20 03 00 00 00 CPU_SUBTYPE_I386_ALL
0x24 08 40 02 00 Offset (in bytes) to beginning of second executable's header ( = 147464 dec)
0x28 28 4f 02 00 Length (in bytes) of first executable ( = 151336 dec)
0x3B 00 00 00 00 Alignment

OS X 10.4.8 boot.efi

00000000h: B9 FA F1 0E 02 00 00 00 07 00 00 00 03 00 00 00 30 00 00 00 21 0D 02 00 00 00 00 00 07 00 00 01 ; ¹úñ.............0...!...........
00000020h: 03 00 00 00 51 0D 02 00 17 13 02 00 00 00 00 00                                                 ; ....Q...........
Offset Data Purpose
0x00 B9 FA F1 0E Magic number 0xEF1FAB9 looks like leetspeak
0x04 02 00 00 00 2 architectures present (0x00000002, Little Endian)
0x08 07 00 00 00 1st arch=i386 (0x0000007, Little Endian)
0x0B 03 00 00 00 CPU_SUBTYPE_I386_ALL
0xF0 30 00 00 00 Offset (in bytes) to beginning of first executable's header ( = 48 dec)
0xF4 21 0D 02 00 Length (in bytes) of first executable ( = 134433 dec)
0xF8 00 00 00 00 Alignment
0xFB 07 00 00 01 2nd arch=x86_64 (0x01000007, little endian)
0x20 03 00 00 00 CPU_SUBTYPE_I386_ALL
0x24 51 0D 02 00 Offset (in bytes) to beginning of second executable's header ( = 134481 dec)
0x28 17 13 02 00 Length (in bytes) of first executable ( = 135959 dec)
0x3B 00 00 00 00 Alignment

Note that the "Unknown" fields are the same between both files - only the offset and length fields have changed.

PE Sections

If the AppleTV boot.efi is split according to the information in the proprietary header, the result is two valid and distinct PE files. Interestingly, the seldom-used checksum field in the "Optional Header" is filled in here (see Section 3.4.2 of the PE/COFF spec above). Combined with the fact that a single-byte change to a safe region of the file (ie, a string resource) is enough to keep the AppleTV from booting successfully, this suggests that the firmware is validating the checksum before beginning execution.

These checksums are not calculated in the usual manner. Microsoft keeps the actual algorithm used for calculating the checksum a secret, but they make a library for calculating the checksum of a PE image available, which produces the following results:

PE Section File Checksum Calculated MS Checksum
1 0xF59B0200 0x000262C5
2 0xCAAD0200 0x0002DD57

The checksum values from the OS X 10.4.8 PE sections are not included here, but are similarly incorrect.

None of the freely available EFI executables (elilo, refit, Intel reference shell implementation, etc) have a checksum value specified at all, although this knowledge is basically useless without knowing the method for calculating the proper checksum.

Experimentation

Experiment Result
Modify the file by shifting both PE sections 4 bytes forward, update prop. header Boots successfully
Build a boot.efi with two copies of the first PE section, update prop. header Fails to boot - question-mark icon
Build a boot.efi with two copies of the second PE section, update prop. header Fails to boot - question-mark icon
Build a boot.efi with the first and second PE sections swapped, update prop. header Fails to boot - question-mark icon
Extract first PE section, rename to boot.efi Fails to boot - question-mark icon
Extract second PE section, rename to boot.efi Fails to boot - question-mark icon

The results of the first experiment are a pleasant surprise, since they indicate that the firmware doesn't validate the entire boot.efi file - only the PE sections contained within. This suggests that if the proper checksum algorithm is discovered, booting a custom EFI image should be within reach.


Update: The EFI System Partition has type 0xEF in the MBR Partition Table scheme, and a specific, well-known, GUID in the GUID Partition Table scheme. It contains boot loader programs, which are EFI executable programs that are loaded and run by the EFI boot manager. Not leetspeek! ;) Information quoted from: http://homepages.tesco.net/J.deBoynePollard/FGA/efi-boot-process.html[1]

Availability

update: the boot.efi file doesn't have to come from the 1.1 image link (which is broken)

the latest image is 2.1.0 http://mesu.apple.com/data/OS/061-5044.20080709.de43E/2Z694-5485-1.dmg and the boot.efi can be found in the same location (/usr/standalone/i386/boot.efi)

Apple's first software update contains a copy of the boot.efi file, for use in other projects. It can be downloaded from http://mesu.apple.com/data/OS/061-2988.20070620.bHy75/2Z694-5248-45.dmg and is located at usr/standalone/i386/boot.efi within the DMG.

Personal tools