Skip to content

Commit 66a1377

Browse files
committed
fix(elf2image): Fix --pad-to-size argument parsing
1 parent 0f0070b commit 66a1377

File tree

2 files changed

+87
-2
lines changed

2 files changed

+87
-2
lines changed

esptool/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -785,10 +785,10 @@ def image_info_cli(ctx, filename: list[tuple[int | None, t.IO[bytes]]]):
785785
)
786786
@click.option(
787787
"--pad-to-size",
788-
type=int,
788+
type=str,
789789
default=None,
790790
help="The block size to pad the final binary image to. "
791-
"Value 0xFF is used for padding.",
791+
"Value 0xFF is used for padding. Supports MB, KB suffixes.",
792792
)
793793
@click.option(
794794
"--ram-only-header",

test/test_imagegen.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,13 @@ def run_elf2image(
160160
print(e.output)
161161
raise
162162

163+
@staticmethod
164+
def assertAllFF(some_bytes):
165+
"""Assert that the given bytes are all 0xFF (erased flash state)"""
166+
assert b"\xff" * len(some_bytes) == some_bytes, (
167+
"Expected all 0xFF bytes, but found different values"
168+
)
169+
163170

164171
class TestESP8266V1Image(BaseTestCase):
165172
ELF = "esp8266-nonosssdk20-iotdemo.elf"
@@ -344,6 +351,84 @@ def test_ram_only_header(self):
344351
image = self._test_elf2image(ELF, BIN, ["--ram-only-header"])
345352
assert len(image.segments) == 2
346353

354+
@pytest.fixture(scope="class")
355+
def reference_bin(self):
356+
BASE_NAME = "esp32-bootloader"
357+
BIN = f"{BASE_NAME}-reference.bin"
358+
self.run_elf2image("esp32", f"{BASE_NAME}.elf")
359+
os.rename(f"{BASE_NAME}.bin", BIN)
360+
yield BIN
361+
# Cleanup the reference binary after the test
362+
try_delete(BIN)
363+
364+
def test_pad_to_size(self, reference_bin: str):
365+
"""Test that --pad-to-size correctly pads output binary to specified size"""
366+
ELF = "esp32-bootloader.elf"
367+
BIN = "esp32-bootloader.bin"
368+
369+
try:
370+
# Generate the padded binary with 1MB size
371+
self.run_elf2image("esp32", ELF, extra_args=["--pad-to-size", "1MB"])
372+
373+
# Get the size of the reference binary
374+
normal_size = os.path.getsize(reference_bin)
375+
376+
# Check that the padded binary is exactly 1MB
377+
padded_size = os.path.getsize(BIN)
378+
expected_size = 0x100000 # 1MB in bytes
379+
assert padded_size == expected_size, (
380+
f"Expected {expected_size} bytes (1MB), got {padded_size} bytes"
381+
)
382+
383+
# Check that the original content is preserved at the beginning
384+
with open(reference_bin, "rb") as f:
385+
original_content = f.read()
386+
with open(BIN, "rb") as f:
387+
padded_content = f.read()
388+
389+
assert padded_content[:normal_size] == original_content, (
390+
"Original content should be preserved at the beginning of padded file"
391+
)
392+
393+
# Check that the padding is filled with 0xFF bytes (erased flash state)
394+
padding = padded_content[normal_size:]
395+
expected_padding_size = expected_size - normal_size
396+
assert len(padding) == expected_padding_size, (
397+
f"Padding should be {expected_padding_size} bytes, got {len(padding)}"
398+
)
399+
self.assertAllFF(padding)
400+
401+
finally:
402+
try_delete(BIN)
403+
404+
@pytest.mark.parametrize("size", ["512KB", "2MB", "4MB"])
405+
def test_pad_to_size_different_sizes(self, size: str, reference_bin: str):
406+
"""Test --pad-to-size with different size values"""
407+
ELF = "esp32-bootloader.elf"
408+
BIN = "esp32-bootloader.bin"
409+
410+
expected_bytes = esptool.util.flash_size_bytes(size)
411+
try:
412+
# Generate the padded binary
413+
self.run_elf2image("esp32", ELF, extra_args=["--pad-to-size", size])
414+
415+
# Check the file size
416+
padded_size = os.path.getsize(BIN)
417+
assert padded_size == expected_bytes, (
418+
f"Expected {expected_bytes} bytes for {size}, got {padded_size}"
419+
)
420+
421+
# Check that padding is 0xFF
422+
with open(BIN, "rb") as f:
423+
padded_content = f.read()
424+
425+
# Get original size from the normal binary and check that padding
426+
normal_size = os.path.getsize(reference_bin)
427+
self.assertAllFF(padded_content[normal_size:])
428+
429+
finally:
430+
try_delete(BIN)
431+
347432

348433
class TestESP8266FlashHeader(BaseTestCase):
349434
def test_2mb(self):

0 commit comments

Comments
 (0)