Evgeny Zinoviev has uploaded this change for review.

View Change

Documentation: Add MacBook internal flashing tutorial

Change-Id: I2650d5d60db7a29a1567e44e89b785def9342df2
Signed-off-by: Evgeny Zinoviev <me@ch1p.io>
---
M Documentation/flash_tutorial/int_flashrom.md
A Documentation/flash_tutorial/int_macbook.md
2 files changed, 294 insertions(+), 0 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/70/38770/1
diff --git a/Documentation/flash_tutorial/int_flashrom.md b/Documentation/flash_tutorial/int_flashrom.md
index 28b534b..0ca59af 100644
--- a/Documentation/flash_tutorial/int_flashrom.md
+++ b/Documentation/flash_tutorial/int_flashrom.md
@@ -16,4 +16,9 @@
flashrom -p internal -w coreboot.rom
```

+## Vendor-specific
+
+- [Lenovo ThinkPad xx30 series](../lenovo/ivb_internal_flashing)
+- [Apple MacBook](int_macbook.md) - 2011-2012 models
+
[flashrom's wiki]: https://www.flashrom.org/Flashrom
diff --git a/Documentation/flash_tutorial/int_macbook.md b/Documentation/flash_tutorial/int_macbook.md
new file mode 100644
index 0000000..b0638ca
--- /dev/null
+++ b/Documentation/flash_tutorial/int_macbook.md
@@ -0,0 +1,289 @@
+# Apple MacBook internal flashing
+
+This page describes a method of flashing coreboot on 2011-2012 models of
+Apple MacBooks. Whether it can be used on other generations of MacBooks
+is unknown.
+
+This is a very delicate prodecure. Be very careful, check everything
+twice, especially the numbers. A single mistake may brick your machine
+and you'll have to flash the backup externally. Given this fact, you
+should have an external means of flashing, just in case.
+
+It was tested and confirmed to work on following models:
+- MacBook Air 5,2
+- MacBook Pro 8,1
+- MacBook Pro 10,1
+
+MacBook Air 4,2 should work too, but it's not tested.
+
+## Introduction
+
+Apple's "Think Different" slogan fits perfectly with their approach to
+firmware security. Besides the fact that they do not use SMM_BWP to
+protect SPI flash from being writable from userspace, they do not even
+protect Flash Descriptor (`fd`) and Management Engine (`me`) regions.
+
+The Intel Flash Descriptor is a data structure of fixed size (4KB)
+stored on the flash chip (resides in `0x0000-0x0fff`), that contains
+various information such as space allocated for each region on the
+flash, access permissions, some chipset configuration and more. In
+particular, it contains access permissions for `fd` and `me` regions.
+Normally they should be read-only in production, but Apple, for whatever
+reasons, keeps them read-write.
+
+Instead, they decided to use SPI Protected Range Registers (PR0-PR4) to
+set protection over `fd`, but here they failed again. Due to a bug in
+their firmware, `0x0000-0x0fff` is not write-protected after cold boot
+and becomes read-only only after resuming from S3. You can dump PRx
+protections by running `flashrom -p internal`.
+
+This is what you should see after a cold boot (if so, then you can use
+this guide):
+```
+PR0: Warning: 0x00190000-0x0066ffff is read-only.
+PR1: Warning: 0x00692000-0x01ffffff is read-only.
+```
+
+And this is after resuming from S3:
+```
+PR0: Warning: 0x00000000-0x00000fff is read-only.
+PR1: Warning: 0x00190000-0x0066ffff is read-only.
+PR2: Warning: 0x00692000-0x01ffffff is read-only.
+```
+
+So, after cold boot flash descriptor is not protected neither by PRx
+registers nor by access permissions bits on the flash descriptor itself.
+Under certain circumstances, **writable flash descriptor allows to flash
+whole SPI flash** by using a couple of tricks.
+
+The idea is that we can shrink ME firmware with me_cleaner, flash small
+coreboot image on the freed space and move reset vector there. Then
+power off, boot coreboot and flash full image, as there will be no more
+PRx set.
+
+## Stage 1. Flashing temporary BIOS
+
+#### Preparations
+
+Dump your ROM:
+```
+flashrom -p internal -r orig.bin
+```
+
+Please save this backup to an external drive. You may need it in case of
+failure.
+
+Extract flash layout:
+```
+ifdtool -f orig_layout.txt orig.bin
+cat orig_layout.txt
+```
+
+You should see something like or exactly this:
+```
+00000000:00000fff fd
+00190000:007fffff bios
+00001000:0018ffff me
+```
+If you compare these regions with what's protected by PR0 and PR1,
+you'll notice that `fd` and `me` regions are fully writable and only
+`bios` is protected. Writable ME region gives us around 1.5 MB which we
+can use for our goals.
+
+Extract flash regions from the dump into separate files:
+```
+ifdtool -x orig.bin
+```
+
+You can see that 3 new files were created:
+```
+ls flash*
+flashregion_0_flashdescriptor.bin flashregion_1_bios.bin flashregion_2_intel_me.bin
+```
+
+The ME firmware is ~1.5 MB in size, but we can truncate it with
+me_cleaner:
+```
+me_cleaner.py -t -r -O flashregion_2_intel_me_truncated.bin flashregion_2_intel_me.bin
+```
+
+The truncated firmware should be around 90K:
+```
+stat --printf=%s flashregion_2_intel_me_truncated.bin
+94208
+```
+
+Rename the original `flashregion_2_intel_me.bin` file to not mix them up
+in future:
+```
+mv flashregion_2_intel_me.bin flashregion_2_intel_me_orig.bin
+```
+
+Now we need to write a new flash layout. 128K is more than enough for
+the "neutered" ME firmware. We can use the rest for new `bios` region,
+but 892K is enough:
+
+```
+00000000:00000fff fd
+00001000:00020fff me
+00021000:000fffff bios
+00100000:007fffff pd
+```
+
+Note that we must allocate the remaining `0x100000-0x7fffff` for
+something to be able to address and flash it in future. Let's just mark
+it as `pd` (which stands for "Platform Data") for now.
+
+Save the new layout to a file `new_layout.txt` and update regions in the
+dump:
+```
+ifdtool -n new_layout.txt orig.bin
+```
+
+The updated image will be saved to `orig.bin.new`. Move it to a
+separate directory for convenience:
+```
+mkdir patched && cd $_
+mv ../orig.bin.new .
+```
+
+Extract flash regions again, now from the updated image:
+```
+fdtool -x orig.bin.new
+```
+
+By now we have new `flashregion_0_flashdescriptor.bin` file with our
+custom layout. Let's also move the patched ME here:
+```
+rm flashregion_2_intel_me.bin
+mv ../flashregion_2_intel_me_truncated.bin .
+```
+
+So far, so good. At this point our preparations for the first stage are
+finished and we're ready to configure coreboot.
+
+#### Configuring and flashing coreboot
+
+Run `make menuconfig` and configure as shown below. Note that you need
+to change **ROM chip size**, **CBFS size** and specify paths to modified
+`flashregion_0_flashdescriptor.bin` and
+`flashregion_2_intel_me_truncated.bin`.
+
+```
+Mainboard --->
+ Mainboard vendor (Apple)
+ Mainboard model () # Set according to your model
+ ROM chip size (1024 KB (1 MB))
+ (0xd0000) Size of CBFS filesystem in ROM
+
+Chipset --->
+ [*] Add Intel descriptor.bin file
+ (/path/to/patched/flashregion_0_flashdescriptor.bin) Path and filename of the descriptor.bin file
+ [*] Add Intel ME/TXE firmware
+ (/path/to/patched/flashregion_2_intel_me_truncated.bin) Path to management engine firmware
+ [ ] Verify the integrity of the supplied ME/TXE firmware
+ [ ] Strip down the Intel ME/TXE firmware
+ Protect flash regions (Unlock flash regions)
+```
+
+Then you need to decide which payload to use. For now, it's recommended
+to use GRUB2. Be sure to include a good config for it that can load variety
+of setups. SeaBIOS works too, but currently needs a patch for internal
+MacBook's keyboard to work.
+
+When configuration is done, run `make` to build coreboot. In the end you
+should have 1024 KB coreboot ROM at `build/coreboot.rom`. Flashrom won't
+accept it, because it's size must match the chip, so we have to make it
+8 MB. Just add 7 MB of zeroes:
+```
+dd if=/dev/zero of=7M.bin bs=1024 count=7168
+```
+```
+cat build/coreboot.rom 7M.bin > coreboot8.rom
+```
+
+Now cross your fingers and flash the new **`fd`** (`0x0000-0x0fff`),
+**`me`** (`0x1000-0x20fff`) and **`bios`** (`0x21000-0xfffff`) regions
+using the layout file:
+```
+flashrom -p internal -w coreboot8.rom -l new_layout.txt -i fd -N
+flashrom -p internal -w coreboot8.rom -l new_layout.txt -i me -N
+flashrom -p internal -w coreboot8.rom -l new_layout.txt -i bios -N
+```
+
+The first stage is completed. Power off the machine now. Reboot won't
+work: new flash descriptor becomes active on cold boot.
+
+On the next boot, if you're lucky and didn't do any mistake, coreboot
+will be loaded from the new `bios` region, and Apple's EFI, that still
+resides in `0x190000-0x7fffff`, will be ignored.
+
+## Stage 2. Flashing full ROM
+
+Now we can flash whole 8 MB chip, because no PRx are set anymore. Let's
+relayout the chip again.
+
+If you want to continue using truncated ME:
+```
+00000000:00000fff fd
+00001000:00020fff me
+00021000:007fffff bios
+```
+
+If you want to flash full ME firmware back:
+```
+00000000:00000fff fd
+00001000:0018ffff me
+00190000:007fffff bios
+```
+
+Save it to `final_layout.txt` and create new flash descriptor again.
+```
+mkdir patched2 && cd $_
+cp ../orig.bin .
+ifdtool -n final_layout.txt orig.bin
+ifdtool -x orig.bin.new
+```
+
+Go back to coreboot directory and run `make menuconfing`.
+
+In the **Mainboard** section change **ROM chip size** back to 8 MB and
+set **Size of CBFS** according to your needs: now you have plenty of
+space. `0x500000` or so should work just fine.
+
+In the **Chipset** section, update paths to the flash descriptor and ME
+firmware files. If you decided to stick to truncated ME, use
+`flashregion_2_intel_me_truncated.bin`, otherwise use
+`flashregion_2_intel_me_orig.bin`.
+
+```
+Mainboard --->
+ ROM chip size (8192 KB (8 MB))
+ (0x500000) Size of CBFS filesystem in ROM
+
+Chipset --->
+ [*] Add Intel descriptor.bin file
+
+ # Use the latest flashdescriptor from the patched2 directory
+ (/path/to/patched2/flashregion_0_flashdescriptor.bin) Path and filename of the descriptor.bin file
+
+ [*] Add Intel ME/TXE firmware
+ (/path/to/patched/flashregion_2_intel_me_truncated.bin) Path to management engine firmware
+ [ ] Verify the integrity of the supplied ME/TXE firmware
+ [ ] Strip down the Intel ME/TXE firmware
+```
+
+Save the config and `make` it again. Then flash `fd` and `bios`
+according to the `final_layout.txt`:
+```
+flashrom -p internal -w build/coreboot.rom -l final_layout.txt -i fd -N
+flashrom -p internal -w build/coreboot.rom -l final_layout.txt -i bios -N
+```
+
+If you changed ME firmware back to original, flash it as well:
+```
+flashrom -p internal -w build/coreboot.rom -l final_layout.txt -i me -N
+```
+
+Stage 2 is completed. Power off (reboot won't work again). On the next
+boot, you will have completely corebooted MacBook.

To view, visit change 38770. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I2650d5d60db7a29a1567e44e89b785def9342df2
Gerrit-Change-Number: 38770
Gerrit-PatchSet: 1
Gerrit-Owner: Evgeny Zinoviev <me@ch1p.io>
Gerrit-MessageType: newchange