Commit 76764638cd774ce8679b71c9843b9b13847d716e
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.
Showing
17 changed files
with
130 additions
and
37 deletions
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 | $(CC) -Wall -Wextra -g -o $@ $< -lusb-1.0 | 2 | $(CC) -Wall -Wextra -g -o $@ $< -lusb-1.0 |
| 3 | 3 | ||
| 4 | %.h: %.bin ./bin2c | 4 | %.h: %.bin ./bin2c |
| @@ -13,11 +13,13 @@ bin2c: bin2c.c | @@ -13,11 +13,13 @@ bin2c: bin2c.c | ||
| 13 | uninstall: | 13 | uninstall: |
| 14 | rm -f /usr/bin/rpiboot | 14 | rm -f /usr/bin/rpiboot |
| 15 | rm -f /usr/share/rpiboot/usbbootcode.bin | 15 | rm -f /usr/share/rpiboot/usbbootcode.bin |
| 16 | + rm -f /usr/share/rpiboot/usbbootcode4.bin | ||
| 16 | rm -f /usr/share/rpiboot/msd.elf | 17 | rm -f /usr/share/rpiboot/msd.elf |
| 18 | + rm -f /usr/share/rpiboot/msd4.elf | ||
| 17 | rm -f /usr/share/rpiboot/buildroot.elf | 19 | rm -f /usr/share/rpiboot/buildroot.elf |
| 18 | rmdir --ignore-fail-on-non-empty /usr/share/rpiboot/ | 20 | rmdir --ignore-fail-on-non-empty /usr/share/rpiboot/ |
| 19 | 21 | ||
| 20 | -clean: | 22 | +clean: |
| 21 | rm -f rpiboot msd/*.h bin2c | 23 | rm -f rpiboot msd/*.h bin2c |
| 22 | 24 | ||
| 23 | .PHONY: uninstall clean | 25 | .PHONY: uninstall clean |
Readme.md
| 1 | # USB boot code | 1 | # USB boot code |
| 2 | 2 | ||
| 3 | This is the USB MSD boot code which should work on the Raspberry Pi model A, Compute Module, Compute | 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 | This version of rpiboot has been modified to work from directories which contain the booting | 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 | ## Building | 18 | ## Building |
| 11 | 19 |
debian/99-rpiboot.rules
debian/control
| @@ -11,4 +11,4 @@ Architecture: any | @@ -11,4 +11,4 @@ Architecture: any | ||
| 11 | Depends: ${shlibs:Depends}, ${misc:Depends} | 11 | Depends: ${shlibs:Depends}, ${misc:Depends} |
| 12 | Description: Raspberry Pi USB booting code | 12 | Description: Raspberry Pi USB booting code |
| 13 | USB MSD boot code which should work on the Raspberry Pi model A, | 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 | rpiboot usr/bin | 1 | rpiboot usr/bin |
| 2 | msd/*.elf usr/share/rpiboot/msd/ | 2 | msd/*.elf usr/share/rpiboot/msd/ |
| 3 | msd/*.bin usr/share/rpiboot/msd/ | 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 | debian/99-rpiboot.rules /lib/udev/rules.d | 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 +3,7 @@ rpiboot: arch-dependent-file-in-usr-share usr/share/rpiboot/msd/start.elf | ||
| 3 | rpiboot: binary-from-other-architecture usr/share/rpiboot/msd/start.elf | 3 | rpiboot: binary-from-other-architecture usr/share/rpiboot/msd/start.elf |
| 4 | rpiboot: unstripped-binary-or-object usr/share/rpiboot/msd/start.elf | 4 | rpiboot: unstripped-binary-or-object usr/share/rpiboot/msd/start.elf |
| 5 | rpiboot: statically-linked-binary usr/share/rpiboot/msd/start.elf | 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
debian/source.lintian-overrides
main.c
| @@ -7,6 +7,8 @@ | @@ -7,6 +7,8 @@ | ||
| 7 | 7 | ||
| 8 | #include "msd/bootcode.h" | 8 | #include "msd/bootcode.h" |
| 9 | #include "msd/start.h" | 9 | #include "msd/start.h" |
| 10 | +#include "msd/bootcode4.h" | ||
| 11 | +#include "msd/start4.h" | ||
| 10 | 12 | ||
| 11 | /* Assume BSD without native fmemopen() if doesn't seem to be glibc */ | 13 | /* Assume BSD without native fmemopen() if doesn't seem to be glibc */ |
| 12 | #if defined(__APPLE__) || (!defined(_GNU_SOURCE) && (!defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200809L)) | 14 | #if defined(__APPLE__) || (!defined(_GNU_SOURCE) && (!defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200809L)) |
| @@ -24,6 +26,10 @@ uint8_t targetPortNo = 99; | @@ -24,6 +26,10 @@ uint8_t targetPortNo = 99; | ||
| 24 | 26 | ||
| 25 | int out_ep; | 27 | int out_ep; |
| 26 | int in_ep; | 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 | typedef struct MESSAGE_S { | 34 | typedef struct MESSAGE_S { |
| 29 | int length; | 35 | int length; |
| @@ -39,6 +45,10 @@ void usage(int error) | @@ -39,6 +45,10 @@ void usage(int error) | ||
| 39 | fprintf(dest, "Boot a Raspberry Pi in device mode either directly into a mass storage device\n"); | 45 | fprintf(dest, "Boot a Raspberry Pi in device mode either directly into a mass storage device\n"); |
| 40 | fprintf(dest, "or provide a set of boot files in a directory from which to boot. This can\n"); | 46 | fprintf(dest, "or provide a set of boot files in a directory from which to boot. This can\n"); |
| 41 | fprintf(dest, "then contain a initramfs to boot through to linux kernel\n\n"); | 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 | fprintf(dest, "rpiboot : Boot the device into mass storage device\n"); | 52 | fprintf(dest, "rpiboot : Boot the device into mass storage device\n"); |
| 43 | fprintf(dest, "rpiboot -d [directory] : Boot the device using the boot files in 'directory'\n"); | 53 | fprintf(dest, "rpiboot -d [directory] : Boot the device using the boot files in 'directory'\n"); |
| 44 | fprintf(dest, "Further options:\n"); | 54 | fprintf(dest, "Further options:\n"); |
| @@ -110,8 +120,47 @@ libusb_device_handle * LIBUSB_CALL open_device_with_vid( | @@ -110,8 +120,47 @@ libusb_device_handle * LIBUSB_CALL open_device_with_vid( | ||
| 110 | desc.idProduct == 0x2764 || | 120 | desc.idProduct == 0x2764 || |
| 111 | desc.idProduct == 0x2711) | 121 | desc.idProduct == 0x2711) |
| 112 | { | 122 | { |
| 123 | + FILE *fp_second_stage = NULL; | ||
| 124 | + FILE *fp_sign = NULL; | ||
| 125 | + const char *second_stage; | ||
| 126 | + | ||
| 113 | if(verbose == 2) | 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 | // Check if we should match against a specific port number | 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,6 +399,10 @@ int second_stage_prep(FILE *fp, FILE *fp_sig) | ||
| 350 | fread(boot_message.signature, 1, sizeof(boot_message.signature), fp_sig); | 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 | second_stage_txbuf = (uint8_t *) malloc(boot_message.length); | 406 | second_stage_txbuf = (uint8_t *) malloc(boot_message.length); |
| 354 | if (second_stage_txbuf == NULL) | 407 | if (second_stage_txbuf == NULL) |
| 355 | { | 408 | { |
| @@ -403,7 +456,7 @@ int second_stage_boot(libusb_device_handle *usb_device) | @@ -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 | FILE * fp = NULL; | 461 | FILE * fp = NULL; |
| 409 | char path[256]; | 462 | char path[256]; |
| @@ -415,7 +468,6 @@ FILE * check_file(char * dir, char *fname) | @@ -415,7 +468,6 @@ FILE * check_file(char * dir, char *fname) | ||
| 415 | return NULL; | 468 | return NULL; |
| 416 | } | 469 | } |
| 417 | 470 | ||
| 418 | - // Check directory first then /usr/share/rpiboot | ||
| 419 | if(dir) | 471 | if(dir) |
| 420 | { | 472 | { |
| 421 | if(overlay&&(pathname[0] != 0)) | 473 | if(overlay&&(pathname[0] != 0)) |
| @@ -438,13 +490,24 @@ FILE * check_file(char * dir, char *fname) | @@ -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 | else | 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 | fp = fmemopen(msd_start_elf, msd_start_elf_len, "rb"); | 509 | fp = fmemopen(msd_start_elf, msd_start_elf_len, "rb"); |
| 510 | + } | ||
| 448 | } | 511 | } |
| 449 | 512 | ||
| 450 | return fp; | 513 | return fp; |
| @@ -485,7 +548,7 @@ int file_server(libusb_device_handle * usb_device) | @@ -485,7 +548,7 @@ int file_server(libusb_device_handle * usb_device) | ||
| 485 | case 0: // Get file size | 548 | case 0: // Get file size |
| 486 | if(fp) | 549 | if(fp) |
| 487 | fclose(fp); | 550 | fclose(fp); |
| 488 | - fp = check_file(directory, message.fname); | 551 | + fp = check_file(directory, message.fname, 1); |
| 489 | if(strlen(message.fname) && fp != NULL) | 552 | if(strlen(message.fname) && fp != NULL) |
| 490 | { | 553 | { |
| 491 | int file_size; | 554 | int file_size; |
| @@ -571,8 +634,6 @@ int file_server(libusb_device_handle * usb_device) | @@ -571,8 +634,6 @@ int file_server(libusb_device_handle * usb_device) | ||
| 571 | 634 | ||
| 572 | int main(int argc, char *argv[]) | 635 | int main(int argc, char *argv[]) |
| 573 | { | 636 | { |
| 574 | - FILE * second_stage; | ||
| 575 | - FILE * fp_sign = NULL; | ||
| 576 | libusb_context *ctx; | 637 | libusb_context *ctx; |
| 577 | libusb_device_handle *usb_device; | 638 | libusb_device_handle *usb_device; |
| 578 | struct libusb_device_descriptor desc; | 639 | struct libusb_device_descriptor desc; |
| @@ -583,31 +644,37 @@ int main(int argc, char *argv[]) | @@ -583,31 +644,37 @@ int main(int argc, char *argv[]) | ||
| 583 | // flush immediately | 644 | // flush immediately |
| 584 | setbuf(stdout, NULL); | 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 | usage(1); | 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 | int ret = libusb_init(&ctx); | 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 "Raspberry Pi USB Boot" Sec_rpiboot | @@ -95,6 +95,7 @@ Section "Raspberry Pi USB Boot" Sec_rpiboot | ||
| 95 | 95 | ||
| 96 | File /r redist | 96 | File /r redist |
| 97 | File /r ..\msd | 97 | File /r ..\msd |
| 98 | + File /r ..\recovery | ||
| 98 | 99 | ||
| 99 | DetailPrint "Installing BCM2708 driver..." | 100 | DetailPrint "Installing BCM2708 driver..." |
| 100 | ExecWait '"$INSTDIR\redist\wdi-simple.exe" -n "Raspberry Pi USB boot" -v 0x0a5c -p 0x2763 -t 0' $0 | 101 | 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 | @@ -103,6 +104,10 @@ Section "Raspberry Pi USB Boot" Sec_rpiboot | ||
| 103 | DetailPrint "Installing BCM2710 driver..." | 104 | DetailPrint "Installing BCM2710 driver..." |
| 104 | ExecWait '"$INSTDIR\redist\wdi-simple.exe" -n "Raspberry Pi USB boot" -v 0x0a5c -p 0x2764 -t 0' $0 | 105 | ExecWait '"$INSTDIR\redist\wdi-simple.exe" -n "Raspberry Pi USB boot" -v 0x0a5c -p 0x2764 -t 0' $0 |
| 105 | DetailPrint "Driver install returned $0" | 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 | File cyggcc_s-1.dll | 112 | File cyggcc_s-1.dll |
| 108 | File cygusb-1.0.dll | 113 | File cygusb-1.0.dll |
| @@ -139,6 +144,7 @@ Section "Uninstall" | @@ -139,6 +144,7 @@ Section "Uninstall" | ||
| 139 | 144 | ||
| 140 | RmDir /r /REBOOTOK $INSTDIR\redist | 145 | RmDir /r /REBOOTOK $INSTDIR\redist |
| 141 | RmDir /r /REBOOTOK $INSTDIR\msd | 146 | RmDir /r /REBOOTOK $INSTDIR\msd |
| 147 | + RmDir /r /REBOOTOK $INSTDIR\recovery | ||
| 142 | RmDir /r /REBOOTOK $INSTDIR\usb_driver | 148 | RmDir /r /REBOOTOK $INSTDIR\usb_driver |
| 143 | 149 | ||
| 144 | Delete $INSTDIR\Uninstall.exe | 150 | Delete $INSTDIR\Uninstall.exe |
win32/rpiboot_setup.exe
No preview for this file type