├── .gitignore ├── nixpkgs.json ├── README.md ├── default.nix ├── autoboot.sh ├── write-protection.md ├── coreboot.nix └── coreboot.config /.gitignore: -------------------------------------------------------------------------------- 1 | Image.lzma 2 | uImage 3 | initramfs.cpio.xz 4 | backups/ 5 | result -------------------------------------------------------------------------------- /nixpkgs.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "https://releases.nixos.org/nixos/21.05/nixos-21.05.961.1f91fd10406/nixexprs.tar.xz", 3 | "sha256": "0c8lgpnh8zfd0a4qgd7x1kxvrfn7kv0wp4bdi0iakyvkl7j62314", 4 | "name": "nixos-21.05.961.1f91fd10406" 5 | } 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nix expressions for (cross) building coreboot for gru-bob chromebook 2 | 3 | These expressions allow building a coreboot ROM with a u-boot payload 4 | for the Rockchip RK3399-based "gru-bob" Chromebook (sold as ASUS 5 | C101PA). Lots of things are still hardcoded, but maybe this can serve 6 | as inspiration for others :) 7 | 8 | ## Building 9 | 10 | `nix-build -A all` produces a directory containing a bunch of handy 11 | files. The most important one is `coreboot.rom`. 12 | 13 | ## Flashing 14 | 15 | I've been flashing this using a SuzyQable. Initial setup for this was nontrivial, see [write-protection.md](write-protection.md). 16 | 17 | For my user to do this, I need permissions to access a couple of things: 18 | 19 | - Relevant USB device nodes in `/dev/bus/usb/001/038` or similar (see lsusb) 20 | - USB tty device nodes (`/dev/ttyUSB[567]` in my case) 21 | 22 | Then I can flash (the Chromebook needs to be on at the beginning and will be forcibly turned off!): 23 | ``` 24 | ./result/flashrom -p raiden_debug:target=AP -r backups/ap-$(date -Iminutes) 25 | ./result/flashrom -p raiden_debug:target=AP -w ./result/coreboot.rom 26 | ``` 27 | This takes quite a long time (usually ~10 minutes to write and verify for me). 28 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | { pkgsPath ? builtins.fetchTarball (builtins.fromJSON (builtins.readFile ./nixpkgs.json)) 2 | , system ? builtins.currentSystem 3 | , pkgs ? import pkgsPath { inherit system; } 4 | , pkgsTarget ? pkgs.pkgsCross.aarch64-multiplatform-musl 5 | }: let 6 | callPackage = pkgs.newScope (pkgs // self); 7 | self = rec { 8 | coreboot = callPackage ./coreboot.nix {}; 9 | u-boot = pkgsTarget.buildUBoot { 10 | name = "u-boot-chromebook_bob"; 11 | defconfig = "chromebook_bob_defconfig"; 12 | filesToInstall = ["u-boot-dtb.bin"]; 13 | postConfigure = '' 14 | sed -i 's/CONFIG_SYS_TEXT_BASE=.*/CONFIG_SYS_TEXT_BASE=0x00a00000/' .config 15 | ''; 16 | enableParallelBuilding = true; 17 | }; 18 | flashrom = pkgs.flashrom.overrideAttrs ({makeFlags ? [], buildInputs ? [], ...}: { 19 | name = "flashrom-ccd"; 20 | src = pkgs.fetchgit { 21 | url = "https://review.coreboot.org/flashrom.git"; 22 | rev = "c7e9a6e15153684672bbadd1fc6baed8247ba0f6"; 23 | sha256 = "09njximl6rdjnpx6d3asvb587q6x3jqbf8107cfygy1b7c051ryd"; 24 | }; 25 | buildInputs = buildInputs ++ [ pkgs.libusb1 ]; 26 | }); 27 | all = pkgs.runCommandNoCC "indigo" {} '' 28 | mkdir -p $out 29 | cp ${coreboot}/coreboot.rom $out/ 30 | cp ${flashrom}/bin/flashrom $out/ 31 | ''; 32 | }; 33 | in self 34 | -------------------------------------------------------------------------------- /autoboot.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ash 2 | set -ex 3 | touch /do-boot 4 | 5 | ( 6 | cd /sys/bus/platform/drivers/sdhci-arasan 7 | mmctries=1000 8 | [[ -e /dev/sda1 ]] && mmctries=20 9 | for try in $(seq $mmctries); do 10 | test -e fe330000.sdhci/mmc_host/mmc*/mmc*/block && found=1 && break 11 | echo fe330000.sdhci > unbind || true 12 | echo fe330000.sdhci > bind 13 | sleep 1 14 | done 15 | test -n "$found" && echo "mmc appeared after $try attempts" | tee /dev/log 16 | ) || true 17 | name=$(echo /sys/bus/platform/drivers/sdhci-arasan/*/mmc_host/mmc*/mmc*/block/*) 18 | name="${name##*/}p1" 19 | 20 | [[ -e "/dev/$name" ]] || name=sda1 21 | 22 | mkdir -p /mnt-new 23 | mount /dev/$name /mnt-new 24 | for fs in proc sys dev ; do 25 | mount --bind /$fs /mnt-new/$fs 26 | done 27 | 28 | 29 | [[ -z "$sys" ]] && sys=/nix/var/nix/profiles/system 30 | kernel=/mnt-new/$(resolvelink /mnt-new "$sys/kernel") 31 | kparams=$(cat "/mnt-new/$(resolvelink /mnt-new "$sys/kernel-params")") 32 | initrd=/mnt-new/$(resolvelink /mnt-new "$sys/initrd") 33 | init=$(resolvelink /mnt-new "$sys/init") 34 | kexec -l "$kernel" --initrd "$initrd" --command-line "$kparams $(cat /proc/cmdline) init=$init" 35 | [[ -e /do-boot ]] && kexec -e 36 | #chroot /mnt-new $sys/sw/bin/kexec -l $sys/kernel --initrd $sys/initrd --command-line "$(cat $sys/kernel-params) $(cat /proc/cmdline) init=$sys/init $extra boot.shell_on_fail " 37 | -------------------------------------------------------------------------------- /write-protection.md: -------------------------------------------------------------------------------- 1 | # Disabling write protection on gru-bob 2 | 3 | PLEASE DO NOT DO THIS IF YOU DO NOT HAVE A SUZYQABLE OR THE KIT TO FLASH THE FIRMWARE DIRECTLY. 4 | 5 | Sources: 6 | - https://wiki.mrchromebox.tech/Firmware_Write_Protect#Disabling_WP_on_CR50_Devices_via_CCD 7 | - https://chromium.googlesource.com/chromiumos/platform/ec/+/master/docs/case_closed_debugging_cr50.md#bob 8 | 9 | 1. Open up the device and remove the write-protection screw. 10 | 11 | 2. Enable developer mode: power on with esc and refresh buttons held, then press ctrl-D and go through the motions 12 | 13 | 3. In a root shell, `gsctool -a -o` and press the power button whenever prompted to (this takes about 3 minutes apparently, but feels like an hour) 14 | 15 | 4. Set a password for your GSC chip (don't lose it, because it can't be reset) using gsctool ??? 16 | 17 | 5. Back up your firmware using flashrom's `-r` operation. 18 | 19 | 6. On the first serial console (Cr50), run the commands: 20 | ``` 21 | ccd set OpenFromUSB Always 22 | ccd set OpenNoDevMode Always 23 | wp false 24 | wp false atboot 25 | ``` 26 | The first two will allow you to open the Cr50 with the password 27 | even if you break your firmware. 28 | 29 | The second two will remove the write protection asserted by the Cr50. 30 | 31 | Once these steps are completed, you will be able to flash your own firmware, using the flashrom included with ChromeOS on the device or your own flashrom—nix expression included in this repo :) 32 | -------------------------------------------------------------------------------- /coreboot.nix: -------------------------------------------------------------------------------- 1 | { stdenv, fetchgit, bc, ncurses, m4, bison, flex, zlib 2 | , lib 3 | , iasl 4 | , buildEnv 5 | , pkgconfig 6 | , pkgsCross 7 | , python3 8 | , rsync 9 | , u-boot }: 10 | let 11 | crossTools = set: [ 12 | set.stdenv.cc 13 | set.buildPackages.nasm 14 | set.buildPackages.binutils 15 | set.buildPackages.gcc-unwrapped 16 | ]; 17 | arm32 = pkgsCross.armv7l-hf-multiplatform; 18 | arm64 = pkgsCross.aarch64-multiplatform; 19 | crossEnv = buildEnv { 20 | name = "coreboot-crossenv"; 21 | paths = crossTools arm64 ++ crossTools arm32 ++ [ pkgsCross.arm-embedded.stdenv.cc ]; 22 | pathsToLink = ["/bin"]; 23 | ignoreCollisions = true; 24 | }; 25 | tool_gcc = tool: set: "${set.stdenv.cc}/bin/${set.stdenv.cc.targetPrefix}${tool}"; 26 | tool_binutils = tool: set: "${set.buildPackages.binutils-unwrapped}/bin/${set.stdenv.cc.targetPrefix}${tool}"; 27 | 28 | makeVars = arch: set: [ 29 | "CC_${arch}=${tool_gcc "cc" set}" 30 | "LD_${arch}=${tool_gcc "ld" set}" 31 | "OBJCOPY_${arch}=${tool_binutils "objcopy" set}" 32 | "OBJDUMP_${arch}=${tool_binutils "objdump" set}" 33 | "NM_${arch}=${tool_binutils "nm" set}" 34 | "AR_${arch}=${tool_binutils "ar" set}" 35 | ]; 36 | 37 | atfSource = fetchgit { 38 | url = "https://review.coreboot.org/arm-trusted-firmware.git"; 39 | rev = "v2.5"; 40 | sha256 = "0w3blkqgmyb5bahlp04hmh8abrflbzy0qg83kmj1x9nv4mw66f3b"; 41 | }; 42 | vbootSource = fetchgit { 43 | url = "https://review.coreboot.org/vboot.git"; 44 | rev = "4e982f1c39da417100e4021fb1c2c370da5f8dd6"; # master 2021-06-15 45 | sha256 = "1fr35gh4c81gb75q6zpf4v9hnvk74ppzdww54fhrr28ahzd73qi6"; 46 | }; 47 | in stdenv.mkDerivation { 48 | name = "coreboot-4.11-${u-boot.pname}"; 49 | src = fetchgit { 50 | url = "https://review.coreboot.org/coreboot.git"; 51 | rev = "4.14"; 52 | sha256 = "06y46bjzkmps84dk5l2ywjcxmsxmqak5cr7sf18s5zv1pm566pqa"; 53 | fetchSubmodules = false; 54 | }; 55 | nativeBuildInputs = [ m4 bison flex bc iasl rsync python3 pkgconfig ]; 56 | buildInputs = [ zlib ]; 57 | makeFlags = makeVars "arm" arm32 ++ makeVars "arm64" arm64 ++ [ 58 | "CROSS_COMPILE_arm64=${arm64.stdenv.cc.targetPrefix}" 59 | "CROSS_COMPILE_arm=${arm32.stdenv.cc.targetPrefix}" 60 | ]; 61 | postPatch = '' 62 | patchShebangs util/xcompile 63 | patchShebangs util/rockchip/make_idb.py 64 | patchShebangs util/genbuild_h/genbuild_h.sh 65 | ''; 66 | configurePhase = '' 67 | runHook preConfigure 68 | 69 | export PATH="${crossEnv}/bin:$PATH" 70 | export ARCH=aarch64 71 | export CPUS=$NIX_BUILD_CORES 72 | grep -v -e 'CONFIG_PAYLOAD_FILE' ${./coreboot.config} > .config 73 | cat >>.config <