Skip to content

Commit ae25771

Browse files
committed
bricks/ev3rt: Make bootable firmware.
ev3rt still expects a microSD card to work properly for the moment, but it no longer needs to contain the uImage.
1 parent 4898777 commit ae25771

File tree

2 files changed

+69
-5
lines changed

2 files changed

+69
-5
lines changed

bricks/ev3rt/Makefile

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,25 +165,30 @@ export EV3RT_BRICK_DIR
165165
export EV3RT_LIB_DIR
166166
export APPLDIRS
167167

168-
all: ev3rt
168+
all: uImage firmware.bin
169+
170+
#TODO: Build our own u-boot image. Use any official firmware for now. u-boot will be extracted from it.
171+
UBOOT_FILE = $(EV3RT_BRICK_DIR)/officialfw.bin
172+
173+
firmware.bin: uImage
174+
python $(EV3RT_BRICK_DIR)/make_bootable_image.py $(UBOOT_FILE) $(BUILD)/uImage $(BUILD)/firmware.bin
169175

170176
ev3rt-config: $(EV3RT_BRICK_DIR) $(BUILD)/libkernel.a prepare-obj-folder
171177
make -C $(BUILD) offset.h kernel_cfg.h
172178

173-
ev3rt-main: $(OBJ)
179+
mkimage: $(OBJ)
174180
make -C $(BUILD) > /dev/null && \
175181
arm-none-eabi-objcopy -O binary $(BUILD)/$(KERNEL) $(BUILD)/$(KERNEL).bin
176182
@mkimage -A arm -O linux -T kernel -C none -a 0xc0008000 -e 0xc0008000 \
177183
-n "TOPPERS/$(KERNEL) Kernel (EV3)" \
178184
-d $(BUILD)/$(KERNEL).bin $(BUILD)/uImage
179185
@chmod +x $(BUILD)/uImage
180186

181-
ev3rt:
187+
uImage:
182188
mkdir -p $(EV3RT_BRICK_DIR)/build
183189
make $(BUILD)/pybricks.cfg
184190
make ev3rt-config
185-
make ev3rt-main
186-
191+
make mkimage
187192
$(BUILD)/libkernel.a: prepare-obj-folder
188193
make -C $(BUILD) libkernel.a
189194

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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

Comments
 (0)