From 76764638cd774ce8679b71c9843b9b13847d716e Mon Sep 17 00:00:00 2001 From: tim Date: Mon, 5 Oct 2020 16:12:14 +0100 Subject: [PATCH] Update rpiboot for CM4 and rationlise -d behaviour. --- Makefile | 6 ++++-- Readme.md | 14 +++++++++++--- debian/99-rpiboot.rules | 2 +- debian/control | 2 +- debian/rpiboot.install | 3 +++ debian/rpiboot.lintian-overrides | 4 ++++ debian/rules | 2 +- debian/source.lintian-overrides | 1 + main.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- msd/bootcode4.bin | Bin 0 -> 99540 bytes msd/start4.elf | Bin 0 -> 293564 bytes recovery/bootcode4.bin | Bin 0 -> 98208 bytes recovery/config.txt | 1 + recovery/pieeprom.bin | Bin 0 -> 524288 bytes recovery/pieeprom.sig | 1 + win32/install_script.nsi | 6 ++++++ win32/rpiboot_setup.exe | Bin 7414437 -> 0 bytes 17 files changed, 130 insertions(+), 37 deletions(-) create mode 100644 msd/bootcode4.bin create mode 100755 msd/start4.elf create mode 100644 recovery/bootcode4.bin create mode 100644 recovery/config.txt create mode 100644 recovery/pieeprom.bin create mode 100644 recovery/pieeprom.sig diff --git a/Makefile b/Makefile index 6d8dc6a..822e714 100755 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -rpiboot: main.c msd/bootcode.h msd/start.h +rpiboot: main.c msd/bootcode.h msd/start.h msd/bootcode4.h msd/start4.h $(CC) -Wall -Wextra -g -o $@ $< -lusb-1.0 %.h: %.bin ./bin2c @@ -13,11 +13,13 @@ bin2c: bin2c.c uninstall: rm -f /usr/bin/rpiboot rm -f /usr/share/rpiboot/usbbootcode.bin + rm -f /usr/share/rpiboot/usbbootcode4.bin rm -f /usr/share/rpiboot/msd.elf + rm -f /usr/share/rpiboot/msd4.elf rm -f /usr/share/rpiboot/buildroot.elf rmdir --ignore-fail-on-non-empty /usr/share/rpiboot/ -clean: +clean: rm -f rpiboot msd/*.h bin2c .PHONY: uninstall clean diff --git a/Readme.md b/Readme.md index 5e09781..6622f67 100644 --- a/Readme.md +++ b/Readme.md @@ -1,11 +1,19 @@ # USB boot code This is the USB MSD boot code which should work on the Raspberry Pi model A, Compute Module, Compute -module 3 and Raspberry Pi Zero. +Module 3, Compute Module 4 and Raspberry Pi Zero. This version of rpiboot has been modified to work from directories which contain the booting -firmware. There is a default directory msd/ which contains bootcode.bin and start.elf to turn -the Raspberry Pi device into a USB Mass Storage Device (MSD). +firmware. There is a msd/ directory which contains bootcode.bin and start.elf to turn +the Raspberry Pi device into a USB Mass Storage Device (MSD). If run without arguments +embedded versions of bootcode.bin and start.elf are used to enable the MSD behaviour. + +For more information run 'rpiboot -h' + +## Compute Module 4 +On Compute Module 4 the EMMC disable jumper (GPIO 40) must be fitted to switch +the ROM to usbboot mode. Otherwise, the SPI EEPROM bootloader image will be loaded +instead. ## Building diff --git a/debian/99-rpiboot.rules b/debian/99-rpiboot.rules index b04d29a..f5e555a 100644 --- a/debian/99-rpiboot.rules +++ b/debian/99-rpiboot.rules @@ -1 +1 @@ -ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="0a5c", ATTR{idProduct}=="276[34]", GROUP="plugdev" +ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="0a5c", ATTR{idProduct}=="27[16][134]", GROUP="plugdev" diff --git a/debian/control b/debian/control index 741358d..f33e700 100644 --- a/debian/control +++ b/debian/control @@ -11,4 +11,4 @@ Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: Raspberry Pi USB booting code USB MSD boot code which should work on the Raspberry Pi model A, - Compute Module, Compute module 3 and Raspberry Pi Zero. + Compute Module, Compute Module 3, Compute Module 4 and Raspberry Pi Zero. diff --git a/debian/rpiboot.install b/debian/rpiboot.install index 39244d8..671ac52 100644 --- a/debian/rpiboot.install +++ b/debian/rpiboot.install @@ -1,4 +1,7 @@ rpiboot usr/bin msd/*.elf usr/share/rpiboot/msd/ msd/*.bin usr/share/rpiboot/msd/ +recovery/*.bin usr/share/rpiboot/recovery/ +recovery/*.sig usr/share/rpiboot/recovery/ +recovery/*.txt usr/share/rpiboot/recovery/ debian/99-rpiboot.rules /lib/udev/rules.d diff --git a/debian/rpiboot.lintian-overrides b/debian/rpiboot.lintian-overrides index b569323..ef9e776 100644 --- a/debian/rpiboot.lintian-overrides +++ b/debian/rpiboot.lintian-overrides @@ -3,3 +3,7 @@ rpiboot: arch-dependent-file-in-usr-share usr/share/rpiboot/msd/start.elf rpiboot: binary-from-other-architecture usr/share/rpiboot/msd/start.elf rpiboot: unstripped-binary-or-object usr/share/rpiboot/msd/start.elf rpiboot: statically-linked-binary usr/share/rpiboot/msd/start.elf +rpiboot: arch-dependent-file-in-usr-share usr/share/rpiboot/msd/start4.elf +rpiboot: binary-from-other-architecture usr/share/rpiboot/msd/start4.elf +rpiboot: unstripped-binary-or-object usr/share/rpiboot/msd/start4.elf +rpiboot: statically-linked-binary usr/share/rpiboot/msd/start4.elf diff --git a/debian/rules b/debian/rules index 385eba2..b37620c 100755 --- a/debian/rules +++ b/debian/rules @@ -4,4 +4,4 @@ dh $@ override_dh_strip: - dh_strip -Xstart.elf + dh_strip -Xstart.elf -Xstart4.elf diff --git a/debian/source.lintian-overrides b/debian/source.lintian-overrides index a761576..3c98968 100644 --- a/debian/source.lintian-overrides +++ b/debian/source.lintian-overrides @@ -1 +1,2 @@ rpiboot: source-is-missing msd/start.elf +rpiboot: source-is-missing msd/start4.elf diff --git a/main.c b/main.c index 7577488..912607b 100644 --- a/main.c +++ b/main.c @@ -7,6 +7,8 @@ #include "msd/bootcode.h" #include "msd/start.h" +#include "msd/bootcode4.h" +#include "msd/start4.h" /* Assume BSD without native fmemopen() if doesn't seem to be glibc */ #if defined(__APPLE__) || (!defined(_GNU_SOURCE) && (!defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200809L)) @@ -24,6 +26,10 @@ uint8_t targetPortNo = 99; int out_ep; int in_ep; +int bcm2711; + +static FILE * check_file(const char * dir, const char *fname, int use_fmem); +static int second_stage_prep(FILE *fp, FILE *fp_sig); typedef struct MESSAGE_S { int length; @@ -39,6 +45,10 @@ void usage(int error) fprintf(dest, "Boot a Raspberry Pi in device mode either directly into a mass storage device\n"); fprintf(dest, "or provide a set of boot files in a directory from which to boot. This can\n"); fprintf(dest, "then contain a initramfs to boot through to linux kernel\n\n"); + fprintf(dest, "To flash the default bootloader EEPROM image on Compute Module 4 run\n"); + fprintf(dest, "rpiboot -d recovery\n\n"); + fprintf(dest, "For more information about the bootloader EEPROM please see:\n"); + fprintf(dest, "https://www.raspberrypi.org/documentation/hardware/raspberrypi/booteeprom.md\n\n"); fprintf(dest, "rpiboot : Boot the device into mass storage device\n"); fprintf(dest, "rpiboot -d [directory] : Boot the device using the boot files in 'directory'\n"); fprintf(dest, "Further options:\n"); @@ -110,8 +120,47 @@ libusb_device_handle * LIBUSB_CALL open_device_with_vid( desc.idProduct == 0x2764 || desc.idProduct == 0x2711) { + FILE *fp_second_stage = NULL; + FILE *fp_sign = NULL; + const char *second_stage; + if(verbose == 2) - printf("Found candidate Compute Module..."); + printf("Found candidate Compute Module..."); + + bcm2711 = (desc.idProduct == 0x2711); + if (bcm2711) + second_stage = "bootcode4.bin"; + else + second_stage = "bootcode.bin"; + + fp_second_stage = check_file(directory, second_stage, 1); + if (!fp_second_stage) + { + fprintf(stderr, "Failed to open %s\n", second_stage); + exit(1); + } + + if (signed_boot && !bcm2711) // Signed boot use a different mechanism on BCM2711 + { + const char *sig_file = "bootcode.sig"; + fp_sign = check_file(directory, sig_file, 1); + if (!fp_sign) + { + fprintf(stderr, "Unable to open '%s'\n", sig_file); + usage(1); + } + } + + if (second_stage_prep(fp_second_stage, fp_sign) != 0) + { + fprintf(stderr, "Failed to prepare the second stage bootcode\n"); + exit(-1); + } + if (fp_second_stage) + fclose(fp_second_stage); + + if (fp_sign) + fclose(fp_sign); /////////////////////////////////////////////////////////////////////// // Check if we should match against a specific port number @@ -350,6 +399,10 @@ int second_stage_prep(FILE *fp, FILE *fp_sig) fread(boot_message.signature, 1, sizeof(boot_message.signature), fp_sig); } + if (second_stage_txbuf) + free(second_stage_txbuf); + second_stage_txbuf = NULL; + second_stage_txbuf = (uint8_t *) malloc(boot_message.length); if (second_stage_txbuf == NULL) { @@ -403,7 +456,7 @@ int second_stage_boot(libusb_device_handle *usb_device) } -FILE * check_file(char * dir, char *fname) +FILE * check_file(const char * dir, const char *fname, int use_fmem) { FILE * fp = NULL; char path[256]; @@ -415,7 +468,6 @@ FILE * check_file(char * dir, char *fname) return NULL; } - // Check directory first then /usr/share/rpiboot if(dir) { if(overlay&&(pathname[0] != 0)) @@ -438,13 +490,24 @@ FILE * check_file(char * dir, char *fname) } } - if(fp == NULL) + // Failover to fmem unless use_fmem is zero in which case this function + // is being used to check if a file exists. + if(fp == NULL && use_fmem) { - if(strcmp(fname, "bootcode.bin") == 0) - fp = fmemopen(msd_bootcode_bin, msd_bootcode_bin_len, "rb"); + if (bcm2711) + { + if(strcmp(fname, "bootcode4.bin") == 0) + fp = fmemopen(msd_bootcode4_bin, msd_bootcode4_bin_len, "rb"); + else if(strcmp(fname, "start4.elf") == 0) + fp = fmemopen(msd_start4_elf, msd_start4_elf_len, "rb"); + } else - if(strcmp(fname, "start.elf") == 0) + { + if(strcmp(fname, "bootcode.bin") == 0) + fp = fmemopen(msd_bootcode_bin, msd_bootcode_bin_len, "rb"); + else if(strcmp(fname, "start.elf") == 0) fp = fmemopen(msd_start_elf, msd_start_elf_len, "rb"); + } } return fp; @@ -485,7 +548,7 @@ int file_server(libusb_device_handle * usb_device) case 0: // Get file size if(fp) fclose(fp); - fp = check_file(directory, message.fname); + fp = check_file(directory, message.fname, 1); if(strlen(message.fname) && fp != NULL) { int file_size; @@ -571,8 +634,6 @@ int file_server(libusb_device_handle * usb_device) int main(int argc, char *argv[]) { - FILE * second_stage; - FILE * fp_sign = NULL; libusb_context *ctx; libusb_device_handle *usb_device; struct libusb_device_descriptor desc; @@ -583,31 +644,37 @@ int main(int argc, char *argv[]) // flush immediately setbuf(stdout, NULL); - // Default to standard msd directory - if(directory == NULL) - directory = "msd"; - - second_stage = check_file(directory, "bootcode.bin"); - if(second_stage == NULL) + // If the boot directory is specified then check that it contains bootcode files. + if (directory) { - fprintf(stderr, "Unable to open 'bootcode.bin' from /usr/share/rpiboot/msd or supplied directory\n"); - usage(1); - } + FILE *f, *f4; - if(signed_boot) - { - fp_sign = check_file(directory, "bootsig.bin"); - if(fp_sign == NULL) + if (verbose) + printf("Boot directory '%s'\n", directory); + + f = check_file(directory, "bootcode.bin", 0); + f4 = check_file(directory, "bootcode4.bin", 0); + if (!f && !f4) { - fprintf(stderr, "Unable to open 'bootsig.bin'\n"); + fprintf(stderr, "No 'bootcode' files found in '%s'\n", directory); usage(1); } - } - if(second_stage_prep(second_stage, fp_sign) != 0) - { - fprintf(stderr, "Failed to prepare the second stage bootcode\n"); - exit(-1); + if (f) + fclose(f); + if (f4) + fclose(f4); + + if (signed_boot) + { + f = check_file(directory, "bootsig.bin", 0); + if (!f) + { + fprintf(stderr, "Unable to open 'bootsig.bin' from %s\n", directory); + usage(1); + } + fclose(f); + } } int ret = libusb_init(&ctx); diff --git a/msd/bootcode4.bin b/msd/bootcode4.bin new file mode 100644 index 0000000..3db6f39 Binary files /dev/null and b/msd/bootcode4.bin differ diff --git a/msd/start4.elf b/msd/start4.elf new file mode 100755 index 0000000..9e244fd Binary files /dev/null and b/msd/start4.elf differ diff --git a/recovery/bootcode4.bin b/recovery/bootcode4.bin new file mode 100644 index 0000000..3a4d201 Binary files /dev/null and b/recovery/bootcode4.bin differ diff --git a/recovery/config.txt b/recovery/config.txt new file mode 100644 index 0000000..5e8e987 --- /dev/null +++ b/recovery/config.txt @@ -0,0 +1 @@ +uart_2ndstage=1 diff --git a/recovery/pieeprom.bin b/recovery/pieeprom.bin new file mode 100644 index 0000000..9ad8bbf Binary files /dev/null and b/recovery/pieeprom.bin differ diff --git a/recovery/pieeprom.sig b/recovery/pieeprom.sig new file mode 100644 index 0000000..464bf01 --- /dev/null +++ b/recovery/pieeprom.sig @@ -0,0 +1 @@ +14362fccbe836696bffea7e3b6eeb1b52c29fe9361a2851d08cd11869b43cb91 diff --git a/win32/install_script.nsi b/win32/install_script.nsi index abcfe12..7cfbddf 100644 --- a/win32/install_script.nsi +++ b/win32/install_script.nsi @@ -95,6 +95,7 @@ Section "Raspberry Pi USB Boot" Sec_rpiboot File /r redist File /r ..\msd + File /r ..\recovery DetailPrint "Installing BCM2708 driver..." ExecWait '"$INSTDIR\redist\wdi-simple.exe" -n "Raspberry Pi USB boot" -v 0x0a5c -p 0x2763 -t 0' $0 @@ -103,6 +104,10 @@ Section "Raspberry Pi USB Boot" Sec_rpiboot DetailPrint "Installing BCM2710 driver..." ExecWait '"$INSTDIR\redist\wdi-simple.exe" -n "Raspberry Pi USB boot" -v 0x0a5c -p 0x2764 -t 0' $0 DetailPrint "Driver install returned $0" + + DetailPrint "Installing BCM2711 driver..." + ExecWait '"$INSTDIR\redist\wdi-simple.exe" -n "Raspberry Pi USB boot" -v 0x0a5c -p 0x2711 -t 0' $0 + DetailPrint "Driver install returned $0" File cyggcc_s-1.dll File cygusb-1.0.dll @@ -139,6 +144,7 @@ Section "Uninstall" RmDir /r /REBOOTOK $INSTDIR\redist RmDir /r /REBOOTOK $INSTDIR\msd + RmDir /r /REBOOTOK $INSTDIR\recovery RmDir /r /REBOOTOK $INSTDIR\usb_driver Delete $INSTDIR\Uninstall.exe diff --git a/win32/rpiboot_setup.exe b/win32/rpiboot_setup.exe index e2532c6..8eb7953 100755 Binary files a/win32/rpiboot_setup.exe and b/win32/rpiboot_setup.exe differ -- libgit2 0.21.4