Skip to content

Commit 8f0ded2

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 4d457a1 commit 8f0ded2

File tree

2 files changed

+58
-5
lines changed

2 files changed

+58
-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: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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+
def make_firmware(uboot_blob, uimage_blob):
21+
22+
if len(uboot_blob) > UBOOT_MAX_SIZE:
23+
print("u-boot file is bigger than expected. Using only the first 256KiB.")
24+
uboot_blob = uboot_blob[:UBOOT_MAX_SIZE]
25+
26+
if len(uimage_blob) > UIMAGE_MAX_SIZE:
27+
raise ValueError("uImage file is too big.")
28+
29+
# Gets combined size, rounded to nearest expected size.
30+
combined_size = UIMAGE_OFFSET + len(uimage_blob)
31+
combined_size = (combined_size + FIRMWARE_ROUND_SIZE) // FIRMWARE_ROUND_SIZE * FIRMWARE_ROUND_SIZE
32+
33+
# Put it all together.
34+
padding_uboot = b'\0' * (UIMAGE_OFFSET - len(uboot_blob))
35+
padding_uimage = b'\0' * (combined_size - UIMAGE_OFFSET - len(uimage_blob))
36+
return uboot_blob + padding_uboot + uimage_blob + padding_uimage
37+
38+
if __name__ == "__main__":
39+
parser = argparse.ArgumentParser(description="Create a bootable EV3 firmware image from a u-boot and uImage file.")
40+
parser.add_argument("uboot", help="The u-boot file, or an official firmware file from which to extract the u-boot.")
41+
parser.add_argument("uimage", help="The uImage file")
42+
parser.add_argument("output", help="The output file")
43+
args = parser.parse_args()
44+
45+
with open(args.uboot, 'rb') as uboot_file, open(args.uimage, 'rb') as uimage_file, open(args.output, 'wb') as output_file:
46+
combined = make_firmware(uboot_file.read(), uimage_file.read())
47+
output_file.write(combined)
48+
print(f"Created {args.output} with size {len(combined) // 1024} KB.")

0 commit comments

Comments
 (0)