Commit 76764638cd774ce8679b71c9843b9b13847d716e

Authored by tim
Committed by Phil Elwell
1 parent 5030f162

Update rpiboot for CM4 and rationlise -d behaviour.

* Add 2711 bootcode and FW binaries with the 4 suffix.
* Use the device descriptor to select the correct bootcode and
  hack it so that bootcode.bin translates to bootcode4.bin on a
  Pi4 allowing the files to remain in the same directory.
* Add the latest best for recovery.bin and pieeprom.bin for CM4
* Update the installer.

Move the second stage preparation until after the device descriptor
has been retrieved because BCM2711 needs a different bootcode.bin.

If the '-d' argument specified then check for bootcode.bin in the
specified directory and don't fail over to the embedded fmem files.

Remove the default 'msd' directory and the references to /usr/share
because the behaviour conflicts with the original change to use
the fmem files.
Makefile
1   -rpiboot: main.c msd/bootcode.h msd/start.h
  1 +rpiboot: main.c msd/bootcode.h msd/start.h msd/bootcode4.h msd/start4.h
2 2 $(CC) -Wall -Wextra -g -o $@ $< -lusb-1.0
3 3  
4 4 %.h: %.bin ./bin2c
... ... @@ -13,11 +13,13 @@ bin2c: bin2c.c
13 13 uninstall:
14 14 rm -f /usr/bin/rpiboot
15 15 rm -f /usr/share/rpiboot/usbbootcode.bin
  16 + rm -f /usr/share/rpiboot/usbbootcode4.bin
16 17 rm -f /usr/share/rpiboot/msd.elf
  18 + rm -f /usr/share/rpiboot/msd4.elf
17 19 rm -f /usr/share/rpiboot/buildroot.elf
18 20 rmdir --ignore-fail-on-non-empty /usr/share/rpiboot/
19 21  
20   -clean:
  22 +clean:
21 23 rm -f rpiboot msd/*.h bin2c
22 24  
23 25 .PHONY: uninstall clean
... ...
Readme.md
1 1 # USB boot code
2 2  
3 3 This is the USB MSD boot code which should work on the Raspberry Pi model A, Compute Module, Compute
4   -module 3 and Raspberry Pi Zero.
  4 +Module 3, Compute Module 4 and Raspberry Pi Zero.
5 5  
6 6 This version of rpiboot has been modified to work from directories which contain the booting
7   -firmware. There is a default directory msd/ which contains bootcode.bin and start.elf to turn
8   -the Raspberry Pi device into a USB Mass Storage Device (MSD).
  7 +firmware. There is a msd/ directory which contains bootcode.bin and start.elf to turn
  8 +the Raspberry Pi device into a USB Mass Storage Device (MSD). If run without arguments
  9 +embedded versions of bootcode.bin and start.elf are used to enable the MSD behaviour.
  10 +
  11 +For more information run 'rpiboot -h'
  12 +
  13 +## Compute Module 4
  14 +On Compute Module 4 the EMMC disable jumper (GPIO 40) must be fitted to switch
  15 +the ROM to usbboot mode. Otherwise, the SPI EEPROM bootloader image will be loaded
  16 +instead.
9 17  
10 18 ## Building
11 19  
... ...
debian/99-rpiboot.rules
1   -ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="0a5c", ATTR{idProduct}=="276[34]", GROUP="plugdev"
  1 +ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="0a5c", ATTR{idProduct}=="27[16][134]", GROUP="plugdev"
... ...
debian/control
... ... @@ -11,4 +11,4 @@ Architecture: any
11 11 Depends: ${shlibs:Depends}, ${misc:Depends}
12 12 Description: Raspberry Pi USB booting code
13 13 USB MSD boot code which should work on the Raspberry Pi model A,
14   - Compute Module, Compute module 3 and Raspberry Pi Zero.
  14 + Compute Module, Compute Module 3, Compute Module 4 and Raspberry Pi Zero.
... ...
debian/rpiboot.install
1 1 rpiboot usr/bin
2 2 msd/*.elf usr/share/rpiboot/msd/
3 3 msd/*.bin usr/share/rpiboot/msd/
  4 +recovery/*.bin usr/share/rpiboot/recovery/
  5 +recovery/*.sig usr/share/rpiboot/recovery/
  6 +recovery/*.txt usr/share/rpiboot/recovery/
4 7 debian/99-rpiboot.rules /lib/udev/rules.d
... ...
debian/rpiboot.lintian-overrides
... ... @@ -3,3 +3,7 @@ rpiboot: arch-dependent-file-in-usr-share usr/share/rpiboot/msd/start.elf
3 3 rpiboot: binary-from-other-architecture usr/share/rpiboot/msd/start.elf
4 4 rpiboot: unstripped-binary-or-object usr/share/rpiboot/msd/start.elf
5 5 rpiboot: statically-linked-binary usr/share/rpiboot/msd/start.elf
  6 +rpiboot: arch-dependent-file-in-usr-share usr/share/rpiboot/msd/start4.elf
  7 +rpiboot: binary-from-other-architecture usr/share/rpiboot/msd/start4.elf
  8 +rpiboot: unstripped-binary-or-object usr/share/rpiboot/msd/start4.elf
  9 +rpiboot: statically-linked-binary usr/share/rpiboot/msd/start4.elf
... ...
debian/rules
... ... @@ -4,4 +4,4 @@
4 4 dh $@
5 5  
6 6 override_dh_strip:
7   - dh_strip -Xstart.elf
  7 + dh_strip -Xstart.elf -Xstart4.elf
... ...
debian/source.lintian-overrides
1 1 rpiboot: source-is-missing msd/start.elf
  2 +rpiboot: source-is-missing msd/start4.elf
... ...
... ... @@ -7,6 +7,8 @@
7 7  
8 8 #include "msd/bootcode.h"
9 9 #include "msd/start.h"
  10 +#include "msd/bootcode4.h"
  11 +#include "msd/start4.h"
10 12  
11 13 /* Assume BSD without native fmemopen() if doesn't seem to be glibc */
12 14 #if defined(__APPLE__) || (!defined(_GNU_SOURCE) && (!defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200809L))
... ... @@ -24,6 +26,10 @@ uint8_t targetPortNo = 99;
24 26  
25 27 int out_ep;
26 28 int in_ep;
  29 +int bcm2711;
  30 +
  31 +static FILE * check_file(const char * dir, const char *fname, int use_fmem);
  32 +static int second_stage_prep(FILE *fp, FILE *fp_sig);
27 33  
28 34 typedef struct MESSAGE_S {
29 35 int length;
... ... @@ -39,6 +45,10 @@ void usage(int error)
39 45 fprintf(dest, "Boot a Raspberry Pi in device mode either directly into a mass storage device\n");
40 46 fprintf(dest, "or provide a set of boot files in a directory from which to boot. This can\n");
41 47 fprintf(dest, "then contain a initramfs to boot through to linux kernel\n\n");
  48 + fprintf(dest, "To flash the default bootloader EEPROM image on Compute Module 4 run\n");
  49 + fprintf(dest, "rpiboot -d recovery\n\n");
  50 + fprintf(dest, "For more information about the bootloader EEPROM please see:\n");
  51 + fprintf(dest, "https://www.raspberrypi.org/documentation/hardware/raspberrypi/booteeprom.md\n\n");
42 52 fprintf(dest, "rpiboot : Boot the device into mass storage device\n");
43 53 fprintf(dest, "rpiboot -d [directory] : Boot the device using the boot files in 'directory'\n");
44 54 fprintf(dest, "Further options:\n");
... ... @@ -110,8 +120,47 @@ libusb_device_handle * LIBUSB_CALL open_device_with_vid(
110 120 desc.idProduct == 0x2764 ||
111 121 desc.idProduct == 0x2711)
112 122 {
  123 + FILE *fp_second_stage = NULL;
  124 + FILE *fp_sign = NULL;
  125 + const char *second_stage;
  126 +
113 127 if(verbose == 2)
114   - printf("Found candidate Compute Module...");
  128 + printf("Found candidate Compute Module...");
  129 +
  130 + bcm2711 = (desc.idProduct == 0x2711);
  131 + if (bcm2711)
  132 + second_stage = "bootcode4.bin";
  133 + else
  134 + second_stage = "bootcode.bin";
  135 +
  136 + fp_second_stage = check_file(directory, second_stage, 1);
  137 + if (!fp_second_stage)
  138 + {
  139 + fprintf(stderr, "Failed to open %s\n", second_stage);
  140 + exit(1);
  141 + }
  142 +
  143 + if (signed_boot && !bcm2711) // Signed boot use a different mechanism on BCM2711
  144 + {
  145 + const char *sig_file = "bootcode.sig";
  146 + fp_sign = check_file(directory, sig_file, 1);
  147 + if (!fp_sign)
  148 + {
  149 + fprintf(stderr, "Unable to open '%s'\n", sig_file);
  150 + usage(1);
  151 + }
  152 + }
  153 +
  154 + if (second_stage_prep(fp_second_stage, fp_sign) != 0)
  155 + {
  156 + fprintf(stderr, "Failed to prepare the second stage bootcode\n");
  157 + exit(-1);
  158 + }
  159 + if (fp_second_stage)
  160 + fclose(fp_second_stage);
  161 +
  162 + if (fp_sign)
  163 + fclose(fp_sign);
115 164  
116 165 ///////////////////////////////////////////////////////////////////////
117 166 // Check if we should match against a specific port number
... ... @@ -350,6 +399,10 @@ int second_stage_prep(FILE *fp, FILE *fp_sig)
350 399 fread(boot_message.signature, 1, sizeof(boot_message.signature), fp_sig);
351 400 }
352 401  
  402 + if (second_stage_txbuf)
  403 + free(second_stage_txbuf);
  404 + second_stage_txbuf = NULL;
  405 +
353 406 second_stage_txbuf = (uint8_t *) malloc(boot_message.length);
354 407 if (second_stage_txbuf == NULL)
355 408 {
... ... @@ -403,7 +456,7 @@ int second_stage_boot(libusb_device_handle *usb_device)
403 456 }
404 457  
405 458  
406   -FILE * check_file(char * dir, char *fname)
  459 +FILE * check_file(const char * dir, const char *fname, int use_fmem)
407 460 {
408 461 FILE * fp = NULL;
409 462 char path[256];
... ... @@ -415,7 +468,6 @@ FILE * check_file(char * dir, char *fname)
415 468 return NULL;
416 469 }
417 470  
418   - // Check directory first then /usr/share/rpiboot
419 471 if(dir)
420 472 {
421 473 if(overlay&&(pathname[0] != 0))
... ... @@ -438,13 +490,24 @@ FILE * check_file(char * dir, char *fname)
438 490 }
439 491 }
440 492  
441   - if(fp == NULL)
  493 + // Failover to fmem unless use_fmem is zero in which case this function
  494 + // is being used to check if a file exists.
  495 + if(fp == NULL && use_fmem)
442 496 {
443   - if(strcmp(fname, "bootcode.bin") == 0)
444   - fp = fmemopen(msd_bootcode_bin, msd_bootcode_bin_len, "rb");
  497 + if (bcm2711)
  498 + {
  499 + if(strcmp(fname, "bootcode4.bin") == 0)
  500 + fp = fmemopen(msd_bootcode4_bin, msd_bootcode4_bin_len, "rb");
  501 + else if(strcmp(fname, "start4.elf") == 0)
  502 + fp = fmemopen(msd_start4_elf, msd_start4_elf_len, "rb");
  503 + }
445 504 else
446   - if(strcmp(fname, "start.elf") == 0)
  505 + {
  506 + if(strcmp(fname, "bootcode.bin") == 0)
  507 + fp = fmemopen(msd_bootcode_bin, msd_bootcode_bin_len, "rb");
  508 + else if(strcmp(fname, "start.elf") == 0)
447 509 fp = fmemopen(msd_start_elf, msd_start_elf_len, "rb");
  510 + }
448 511 }
449 512  
450 513 return fp;
... ... @@ -485,7 +548,7 @@ int file_server(libusb_device_handle * usb_device)
485 548 case 0: // Get file size
486 549 if(fp)
487 550 fclose(fp);
488   - fp = check_file(directory, message.fname);
  551 + fp = check_file(directory, message.fname, 1);
489 552 if(strlen(message.fname) && fp != NULL)
490 553 {
491 554 int file_size;
... ... @@ -571,8 +634,6 @@ int file_server(libusb_device_handle * usb_device)
571 634  
572 635 int main(int argc, char *argv[])
573 636 {
574   - FILE * second_stage;
575   - FILE * fp_sign = NULL;
576 637 libusb_context *ctx;
577 638 libusb_device_handle *usb_device;
578 639 struct libusb_device_descriptor desc;
... ... @@ -583,31 +644,37 @@ int main(int argc, char *argv[])
583 644 // flush immediately
584 645 setbuf(stdout, NULL);
585 646  
586   - // Default to standard msd directory
587   - if(directory == NULL)
588   - directory = "msd";
589   -
590   - second_stage = check_file(directory, "bootcode.bin");
591   - if(second_stage == NULL)
  647 + // If the boot directory is specified then check that it contains bootcode files.
  648 + if (directory)
592 649 {
593   - fprintf(stderr, "Unable to open 'bootcode.bin' from /usr/share/rpiboot/msd or supplied directory\n");
594   - usage(1);
595   - }
  650 + FILE *f, *f4;
596 651  
597   - if(signed_boot)
598   - {
599   - fp_sign = check_file(directory, "bootsig.bin");
600   - if(fp_sign == NULL)
  652 + if (verbose)
  653 + printf("Boot directory '%s'\n", directory);
  654 +
  655 + f = check_file(directory, "bootcode.bin", 0);
  656 + f4 = check_file(directory, "bootcode4.bin", 0);
  657 + if (!f && !f4)
601 658 {
602   - fprintf(stderr, "Unable to open 'bootsig.bin'\n");
  659 + fprintf(stderr, "No 'bootcode' files found in '%s'\n", directory);
603 660 usage(1);
604 661 }
605   - }
606 662  
607   - if(second_stage_prep(second_stage, fp_sign) != 0)
608   - {
609   - fprintf(stderr, "Failed to prepare the second stage bootcode\n");
610   - exit(-1);
  663 + if (f)
  664 + fclose(f);
  665 + if (f4)
  666 + fclose(f4);
  667 +
  668 + if (signed_boot)
  669 + {
  670 + f = check_file(directory, "bootsig.bin", 0);
  671 + if (!f)
  672 + {
  673 + fprintf(stderr, "Unable to open 'bootsig.bin' from %s\n", directory);
  674 + usage(1);
  675 + }
  676 + fclose(f);
  677 + }
611 678 }
612 679  
613 680 int ret = libusb_init(&ctx);
... ...
msd/bootcode4.bin 0 → 100644
No preview for this file type
msd/start4.elf 0 → 100755
No preview for this file type
recovery/bootcode4.bin 0 → 100644
No preview for this file type
recovery/config.txt 0 → 100644
  1 +uart_2ndstage=1
... ...
recovery/pieeprom.bin 0 → 100644
No preview for this file type
recovery/pieeprom.sig 0 → 100644
  1 +14362fccbe836696bffea7e3b6eeb1b52c29fe9361a2851d08cd11869b43cb91
... ...
win32/install_script.nsi
... ... @@ -95,6 +95,7 @@ Section &quot;Raspberry Pi USB Boot&quot; Sec_rpiboot
95 95  
96 96 File /r redist
97 97 File /r ..\msd
  98 + File /r ..\recovery
98 99  
99 100 DetailPrint "Installing BCM2708 driver..."
100 101 ExecWait '"$INSTDIR\redist\wdi-simple.exe" -n "Raspberry Pi USB boot" -v 0x0a5c -p 0x2763 -t 0' $0
... ... @@ -103,6 +104,10 @@ Section &quot;Raspberry Pi USB Boot&quot; Sec_rpiboot
103 104 DetailPrint "Installing BCM2710 driver..."
104 105 ExecWait '"$INSTDIR\redist\wdi-simple.exe" -n "Raspberry Pi USB boot" -v 0x0a5c -p 0x2764 -t 0' $0
105 106 DetailPrint "Driver install returned $0"
  107 +
  108 + DetailPrint "Installing BCM2711 driver..."
  109 + ExecWait '"$INSTDIR\redist\wdi-simple.exe" -n "Raspberry Pi USB boot" -v 0x0a5c -p 0x2711 -t 0' $0
  110 + DetailPrint "Driver install returned $0"
106 111  
107 112 File cyggcc_s-1.dll
108 113 File cygusb-1.0.dll
... ... @@ -139,6 +144,7 @@ Section &quot;Uninstall&quot;
139 144  
140 145 RmDir /r /REBOOTOK $INSTDIR\redist
141 146 RmDir /r /REBOOTOK $INSTDIR\msd
  147 + RmDir /r /REBOOTOK $INSTDIR\recovery
142 148 RmDir /r /REBOOTOK $INSTDIR\usb_driver
143 149  
144 150 Delete $INSTDIR\Uninstall.exe
... ...
win32/rpiboot_setup.exe
No preview for this file type