|
| 1 | +import argparse |
| 2 | + |
| 3 | +# Expected layout of the firmware image: |
| 4 | +# |
| 5 | +# u-boot.bin can be the first 256KiB from official firmware or a custom U-Boot. |
| 6 | +# |
| 7 | +# | Image (file) | Start Addr. | Max. Size | Notes |
| 8 | +# +--------------------+-------------+-------------------+---------- |
| 9 | +# | u-boot.bin | 0x0 | 0x40000 (256KiB) | |
| 10 | +# | da850-lego-ev3.dtb | 0x40000 | 0x10000 (64KiB) | Not used. |
| 11 | +# | uImage | 0x50000 | 0x400000 (4MiB) | Smaller size is allowed. |
| 12 | +# | rootfs (squashfs) | 0x450000 | 0xa00000 (10MiB) | Not used. |
| 13 | + |
| 14 | + |
| 15 | +UBOOT_MAX_SIZE = 256 * 1024 |
| 16 | +UIMAGE_MAX_SIZE = 4 * 1024 * 1024 |
| 17 | +UIMAGE_OFFSET = 0x50000 |
| 18 | +FIRMWARE_ROUND_SIZE = 256 * 1024 |
| 19 | + |
| 20 | + |
| 21 | +def make_firmware(uboot_blob, uimage_blob): |
| 22 | + |
| 23 | + if len(uboot_blob) > UBOOT_MAX_SIZE: |
| 24 | + print("u-boot file is bigger than expected. Using only the first 256KiB.") |
| 25 | + uboot_blob = uboot_blob[:UBOOT_MAX_SIZE] |
| 26 | + |
| 27 | + if len(uimage_blob) > UIMAGE_MAX_SIZE: |
| 28 | + raise ValueError("uImage file is too big.") |
| 29 | + |
| 30 | + # Gets combined size, rounded to nearest expected size. |
| 31 | + combined_size = UIMAGE_OFFSET + len(uimage_blob) |
| 32 | + combined_size = ( |
| 33 | + (combined_size + FIRMWARE_ROUND_SIZE) // FIRMWARE_ROUND_SIZE * FIRMWARE_ROUND_SIZE |
| 34 | + ) |
| 35 | + |
| 36 | + # Put it all together. |
| 37 | + padding_uboot = b"\0" * (UIMAGE_OFFSET - len(uboot_blob)) |
| 38 | + padding_uimage = b"\0" * (combined_size - UIMAGE_OFFSET - len(uimage_blob)) |
| 39 | + return uboot_blob + padding_uboot + uimage_blob + padding_uimage |
| 40 | + |
| 41 | + |
| 42 | +if __name__ == "__main__": |
| 43 | + parser = argparse.ArgumentParser( |
| 44 | + description="Create a bootable EV3 firmware image from a u-boot and uImage file." |
| 45 | + ) |
| 46 | + parser.add_argument( |
| 47 | + "uboot", |
| 48 | + help="The u-boot file, or an official firmware file from which to extract the u-boot.", |
| 49 | + ) |
| 50 | + parser.add_argument("uimage", help="The uImage file") |
| 51 | + parser.add_argument("output", help="The output file") |
| 52 | + args = parser.parse_args() |
| 53 | + |
| 54 | + with open(args.uboot, "rb") as uboot_file, open(args.uimage, "rb") as uimage_file, open( |
| 55 | + args.output, "wb" |
| 56 | + ) as output_file: |
| 57 | + combined = make_firmware(uboot_file.read(), uimage_file.read()) |
| 58 | + output_file.write(combined) |
| 59 | + print(f"Created {args.output} with size {len(combined) // 1024} KB.") |
0 commit comments