fix(elf2image): Try to correct MMU page size if not specified

This commit fixes issue with using elf2image command without --flash-mmu-page-size.
In that case, app info segment might be incorrectly placed in the image.
This is fixed by checking if app info segment is present and if so,
use page size from it or from its alignment.
Closes https://github.com/espressif/esptool/issues/1062
This commit is contained in:
Jaroslav Burian
2025-02-06 10:54:16 +01:00
parent 447de60158
commit d9afa9cd64
8 changed files with 344 additions and 101 deletions

View File

@@ -11,7 +11,7 @@ import os
import re
import struct
import tempfile
from typing import IO, Optional
from typing import IO, Optional, Tuple
from intelhex import HexRecordError, IntelHex
@@ -180,6 +180,7 @@ class ELFSection(ImageSegment):
class BaseFirmwareImage(object):
SEG_HEADER_LEN = 8
SHA256_DIGEST_LEN = 32
MMU_PAGE_SIZE_CONF: Tuple[int, ...] = ()
""" Base class with common firmware image functions """
@@ -621,6 +622,8 @@ class ESP32FirmwareImage(BaseFirmwareImage):
IROM_ALIGN = 65536
MMU_PAGE_SIZE_CONF: Tuple[int, ...] = (IROM_ALIGN,)
def __init__(self, load_file=None, append_digest=True, ram_only_header=False):
super(ESP32FirmwareImage, self).__init__()
self.secure_pad = None
@@ -1128,12 +1131,13 @@ class ESP32C2FirmwareImage(ESP32FirmwareImage):
"""ESP32C2 Firmware Image almost exactly the same as ESP32FirmwareImage"""
ROM_LOADER = ESP32C2ROM
MMU_PAGE_SIZE_CONF = (16384, 32768, 65536)
def set_mmu_page_size(self, size):
if size not in [16384, 32768, 65536]:
if size not in self.MMU_PAGE_SIZE_CONF:
valid_sizes = ", ".join(f"{x // 1024}KB" for x in self.MMU_PAGE_SIZE_CONF)
raise FatalError(
"{} bytes is not a valid ESP32-C2 page size, "
"select from 64KB, 32KB, 16KB.".format(size)
f"{size} bytes is not a valid {self.ROM_LOADER.CHIP_NAME} page size, select from {valid_sizes}."
)
self.IROM_ALIGN = size
@@ -1145,12 +1149,13 @@ class ESP32C6FirmwareImage(ESP32FirmwareImage):
"""ESP32C6 Firmware Image almost exactly the same as ESP32FirmwareImage"""
ROM_LOADER = ESP32C6ROM
MMU_PAGE_SIZE_CONF = (8192, 16384, 32768, 65536)
def set_mmu_page_size(self, size):
if size not in [8192, 16384, 32768, 65536]:
if size not in self.MMU_PAGE_SIZE_CONF:
valid_sizes = ", ".join(f"{x // 1024}KB" for x in self.MMU_PAGE_SIZE_CONF)
raise FatalError(
"{} bytes is not a valid ESP32-C6 page size, "
"select from 64KB, 32KB, 16KB, 8KB.".format(size)
f"{size} bytes is not a valid {self.ROM_LOADER.CHIP_NAME} page size, select from {valid_sizes}."
)
self.IROM_ALIGN = size
@@ -1167,8 +1172,8 @@ class ESP32C61FirmwareImage(ESP32C6FirmwareImage):
ESP32C61ROM.BOOTLOADER_IMAGE = ESP32C61FirmwareImage
class ESP32C5FirmwareImage(ESP32C6FirmwareImage):
"""ESP32C5 Firmware Image almost exactly the same as ESP32C6FirmwareImage"""
class ESP32C5FirmwareImage(ESP32FirmwareImage):
"""ESP32C5 Firmware Image almost exactly the same as ESP32FirmwareImage"""
ROM_LOADER = ESP32C5ROM

View File

@@ -11,7 +11,6 @@ import sys
import time
import zlib
import itertools
import re
from intelhex import IntelHex
from serial import SerialException
@@ -752,20 +751,53 @@ def write_flash(esp, args):
else:
esp.flash_finish(False)
if args.verify:
print("Verifying just-written flash...")
print(
"(This option is deprecated, "
"flash contents are now always read back after flashing.)"
)
# If some encrypted files have been flashed,
# print a warning saying that we won't check them
if args.encrypt or args.encrypt_files is not None:
print("WARNING: - cannot verify encrypted files, they will be ignored")
# Call verify_flash function only if there is at least
# one non-encrypted file flashed
if not args.encrypt:
verify_flash(esp, args)
def _parse_app_info(app_info_segment):
"""
Check if correct magic word is present in the app_info and parse the app_info struct
"""
app_info = app_info_segment[:256]
# More info about the app_info struct can be found at:
# https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/app_image_format.html#application-description
APP_DESC_STRUCT_FMT = "<II" + "8s" + "32s32s16s16s32s32sHHB" + "3s" + "72s"
(
magic_word,
secure_version,
reserv1,
version,
project_name,
time,
date,
idf_ver,
app_elf_sha256,
min_efuse_blk_rev_full,
max_efuse_blk_rev_full,
mmu_page_size,
reserv3,
reserv2,
) = struct.unpack(APP_DESC_STRUCT_FMT, app_info)
if magic_word != 0xABCD5432:
return None
return {
"magic_word": magic_word,
"secure_version": secure_version,
"reserv1": reserv1,
"version": version.decode("utf-8"),
"project_name": project_name.decode("utf-8"),
"time": time.decode("utf-8"),
"date": date.decode("utf-8"),
"idf_ver": idf_ver.decode("utf-8"),
"app_elf_sha256": hexify(app_elf_sha256, uppercase=False),
"min_efuse_blk_rev_full": f"{min_efuse_blk_rev_full // 100}.{min_efuse_blk_rev_full % 100}",
"max_efuse_blk_rev_full": f"{max_efuse_blk_rev_full // 100}.{max_efuse_blk_rev_full % 100}",
"mmu_page_size": f"{2 ** mmu_page_size // 1024} KB"
if mmu_page_size != 0
else None,
"reserv3": reserv3,
"reserv2": reserv2,
}
def image_info(args):
@@ -872,14 +904,14 @@ def image_info(args):
"{} {} {} {} {}".format("-" * 7, "-" * 7, "-" * 10, "-" * 10, "-" * 12)
)
format_str = "{:7} {:#07x} {:#010x} {:#010x} {}"
app_desc = None
app_desc_seg = None
bootloader_desc = None
for idx, seg in enumerate(image.segments):
segs = seg.get_memory_type(image)
seg_name = ", ".join(segs)
# The DROM segment starts with the esp_app_desc_t struct
if "DROM" in segs and app_desc is None:
app_desc = seg.data[:256]
if "DROM" in segs and app_desc_seg is None:
app_desc_seg = seg.data[:256]
elif "DRAM" in segs:
# The DRAM segment starts with the esp_bootloader_desc_t struct
if len(seg.data) >= 80:
@@ -916,51 +948,27 @@ def image_info(args):
except AttributeError:
pass # ESP8266 image has no append_digest field
if app_desc:
APP_DESC_STRUCT_FMT = "<II" + "8s" + "32s32s16s16s32s32sHHB" + "3s" + "72s"
(
magic_word,
secure_version,
reserv1,
version,
project_name,
time,
date,
idf_ver,
app_elf_sha256,
min_efuse_blk_rev_full,
max_efuse_blk_rev_full,
mmu_page_size,
reserv3,
reserv2,
) = struct.unpack(APP_DESC_STRUCT_FMT, app_desc)
if magic_word == 0xABCD5432:
if app_desc_seg:
app_desc = _parse_app_info(app_desc_seg)
if app_desc:
print()
title = "Application information"
print(title)
print("=" * len(title))
print(f'Project name: {project_name.decode("utf-8")}')
print(f'App version: {version.decode("utf-8")}')
print(f'Compile time: {date.decode("utf-8")} {time.decode("utf-8")}')
print(f"ELF file SHA256: {hexify(app_elf_sha256, uppercase=False)}")
print(f'ESP-IDF: {idf_ver.decode("utf-8")}')
print(f'Project name: {app_desc["project_name"]}')
print(f'App version: {app_desc["version"]}')
print(f'Compile time: {app_desc["date"]} {app_desc["time"]}')
print(f"ELF file SHA256: {app_desc['app_elf_sha256']}")
print(f'ESP-IDF: {app_desc["idf_ver"]}')
print(
f"Minimal eFuse block revision: {min_efuse_blk_rev_full // 100}.{min_efuse_blk_rev_full % 100}"
f"Minimal eFuse block revision: {app_desc['min_efuse_blk_rev_full']}"
)
print(
f"Maximal eFuse block revision: {max_efuse_blk_rev_full // 100}.{max_efuse_blk_rev_full % 100}"
f"Maximal eFuse block revision: {app_desc['max_efuse_blk_rev_full']}"
)
# MMU page size is only available in ESP-IDF v5.4 and later
# regex matches major and minor version numbers, idf_ver can look like "v5.4.1-dirty"
ver = re.match(r"v(\d+)\.(\d+)", idf_ver.decode("utf-8"))
if ver:
major, minor = ver.groups()
if int(major) >= 5 and int(minor) >= 4:
print(f"MMU page size: {2 ** mmu_page_size // 1024} KB")
print(f"Secure version: {secure_version}")
if app_desc["mmu_page_size"]:
print(f"MMU page size: {app_desc['mmu_page_size']}")
print(f"Secure version: {app_desc['secure_version']}")
elif bootloader_desc:
BOOTLOADER_DESC_STRUCT_FMT = "<B" + "3s" + "I32s24s" + "16s"
@@ -1112,6 +1120,39 @@ def elf2image(args):
if args.flash_mmu_page_size:
image.set_mmu_page_size(flash_size_bytes(args.flash_mmu_page_size))
else:
appdesc_seg = None
for seg in e.sections:
if ".flash.appdesc" in seg.name:
appdesc_seg = seg
break
# If ELF file contains app description segment, which is in flash memory (RAM build has it too, but does not have MMU page size) and chip has configurable MMU page size.
if (
appdesc_seg
and image.is_flash_addr(appdesc_seg.addr)
and image.MMU_PAGE_SIZE_CONF
):
app_desc = _parse_app_info(appdesc_seg.data)
if app_desc:
# MMU page size is specified in app description segment since ESP-IDF v5.4
if app_desc["mmu_page_size"]:
image.set_mmu_page_size(flash_size_bytes(app_desc["mmu_page_size"]))
# Try to set the correct MMU page size based on the app description starting address which,
# without image + extended header (24 bytes) and segment header (8 bytes), should be aligned to MMU page size.
else:
for mmu_page_size in reversed(image.MMU_PAGE_SIZE_CONF):
if (appdesc_seg.addr - 24 - 8) % mmu_page_size == 0:
image.set_mmu_page_size(mmu_page_size)
print(
f"MMU page size not specified, set to {image.IROM_ALIGN // 1024} KB"
)
break
else:
print(
"Warning: App description segment is not aligned to MMU page size, "
"probably linker script issue or wrong MMU page size. "
"Try to set MMU page size parameter manually."
)
# ELFSection is a subclass of ImageSegment, so can use interchangeably
image.segments = e.segments if args.use_segments else e.sections
@@ -1123,6 +1164,10 @@ def elf2image(args):
if args.elf_sha256_offset:
image.elf_sha256 = e.sha256()
image.elf_sha256_offset = args.elf_sha256_offset
# If the ELF file contains an app_desc section, put the SHA256 digest at the correct offset
elif any(".flash.appdesc" in seg.name for seg in image.segments):
image.elf_sha256 = e.sha256()
image.elf_sha256_offset = 0xB0
if args.ram_only_header:
print(

Binary file not shown.

View File

@@ -0,0 +1,18 @@
CC = riscv32-esp-elf-gcc
CFLAGS = -Os -ffreestanding -nostdlib
LDFLAGS = -T esp32c6-appdesc.ld
TARGET = esp32c6-appdesc.elf
SRC = main.c
OBJ = main.o
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJ) $(TARGET)

View File

@@ -0,0 +1,16 @@
MEMORY
{
/**
* 0x42000000 is start of flash + 0x20 for image + extended header and segment header
* 0x14c is length of esp_app_desc_t structure
*/
drom_seg (R) : org = 0x42000020, len = 0x14c
}
SECTIONS
{
.flash.appdesc :
{
KEEP(*(.flash.appdesc))
} > drom_seg
}

View File

@@ -0,0 +1,45 @@
#include <stdint.h>
// This is the structure of the application description section in the binary image (taken from ESP-IDF).
typedef struct {
uint32_t magic_word;
uint32_t secure_version;
uint32_t reserv1[2];
char version[32];
char project_name[32];
char time[16];
char date[16];
char idf_ver[32];
uint8_t app_elf_sha256[32];
uint16_t min_efuse_blk_rev_full;
uint16_t max_efuse_blk_rev_full;
uint8_t mmu_page_size;
uint8_t reserv3[3];
uint32_t reserv2[18];
} esp_app_desc_t;
__attribute__((section(".flash.appdesc")))
esp_app_desc_t my_app_desc = {
.magic_word = 0xABCD5432,
.secure_version = 0xffffffff,
.reserv1 = {0xffffffff, 0xffffffff},
.version = "_______________________________",
.project_name = "-------------------------------",
.time = "xxxxxxxxxxxxxxx",
.date = "yyyyyyyyyyyyyyy",
.idf_ver = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz",
.app_elf_sha256 = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
.min_efuse_blk_rev_full = 0xffff,
.max_efuse_blk_rev_full = 0xffff,
.mmu_page_size = 0,
.reserv3 = {0xff, 0xff, 0xff},
.reserv2 = {
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff
},
};

View File

@@ -5,6 +5,7 @@ import re
import struct
import subprocess
import sys
import math
from conftest import need_to_install_package_err
@@ -138,7 +139,9 @@ class BaseTestCase:
"warning" not in output.lower()
), "Should be no warnings in image_info output"
def run_elf2image(self, chip, elf_path, version=None, extra_args=[]):
def run_elf2image(
self, chip, elf_path, version=None, extra_args=[], allow_warnings=False
):
"""Run elf2image on elf_path"""
cmd = [sys.executable, "-m", "esptool", "--chip", chip, "elf2image"]
if version is not None:
@@ -149,9 +152,10 @@ class BaseTestCase:
output = subprocess.check_output(cmd)
output = output.decode("utf-8")
print(output)
assert (
"warning" not in output.lower()
), "elf2image should not output warnings"
if not allow_warnings:
assert (
"warning" not in output.lower()
), "elf2image should not output warnings"
except subprocess.CalledProcessError as e:
print(e.output)
raise
@@ -390,15 +394,16 @@ class TestESP32FlashHeader(BaseTestCase):
class TestELFSHA256(BaseTestCase):
ELF = "esp32-app-cust-ver-info.elf"
ELF = "esp32c6-appdesc.elf"
SHA_OFFS = 0xB0 # absolute offset of the SHA in the .bin file
BIN = "esp32-app-cust-ver-info.bin"
BIN = "esp32c6-appdesc.bin"
"""
esp32-app-cust-ver-info.elf was built with the following application version info:
esp32c6-appdesc.elf was built with the following application version info:
const __attribute__((section(".rodata_desc"))) esp_app_desc_t esp_app_desc = {
.magic_word = 0xffffffff,
__attribute__((section(".flash.appdesc")))
esp_app_desc_t my_app_desc = {
.magic_word = 0xABCD5432,
.secure_version = 0xffffffff,
.reserv1 = {0xffffffff, 0xffffffff},
.version = "_______________________________",
@@ -406,21 +411,28 @@ class TestELFSHA256(BaseTestCase):
.time = "xxxxxxxxxxxxxxx",
.date = "yyyyyyyyyyyyyyy",
.idf_ver = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz",
.app_elf_sha256 =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
.reserv2 = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff},
.app_elf_sha256 = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
.min_efuse_blk_rev_full = 0xffff,
.max_efuse_blk_rev_full = 0xffff,
.mmu_page_size = 0,
.reserv3 = {0xff, 0xff, 0xff},
.reserv2 = {
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff
},
};
This leaves zeroes only for the fields of SHA-256 and the test will fail
if the placement of zeroes are tested at the wrong place.
00000000: e907 0020 780f 0840 ee00 0000 0000 0000 ... x..@........
00000010: 0000 0000 0000 0001 2000 403f 605a 0000 ........ .@?`Z..
00000020: ffff ffff ffff ffff ffff ffff ffff ffff ................
00000000: e901 0000 2000 0042 ee00 0000 0d00 0000 .... ..B........
00000010: 00ff ff00 0000 0001 2000 0042 0001 0000 ........ ..B....
00000020: 3254 cdab ffff ffff ffff ffff ffff ffff 2T..............
00000030: 5f5f 5f5f 5f5f 5f5f 5f5f 5f5f 5f5f 5f5f ________________
00000040: 5f5f 5f5f 5f5f 5f5f 5f5f 5f5f 5f5f 5f00 _______________.
00000050: 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d ----------------
@@ -431,37 +443,46 @@ class TestELFSHA256(BaseTestCase):
000000a0: 7a7a 7a7a 7a7a 7a7a 7a7a 7a7a 7a7a 7a00 zzzzzzzzzzzzzzz.
000000b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ SHA-256 here
000000c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000d0: ffff ffff ffff ffff ffff ffff ffff ffff ................
000000d0: ffff ffff 00ff ffff ffff ffff ffff ffff ................
000000e0: ffff ffff ffff ffff ffff ffff ffff ffff ................
000000f0: ffff ffff ffff ffff ffff ffff ffff ffff ................
00000100: ffff ffff ffff ffff ffff ffff ffff ffff ................
00000110: ffff ffff ffff ffff ffff ffff ffff ffff ................
00000120: 6370 755f 7374 6172 7400 0000 1b5b 303b cpu_start....[0;
"""
def test_binary_patched(self):
def verify_sha256(self, elf_path, bin_path):
image = esptool.bin_image.LoadFirmwareImage("esp32c6", bin_path)
rodata_segment = image.segments[0]
bin_sha256 = rodata_segment.data[
self.SHA_OFFS - 0x20 : self.SHA_OFFS - 0x20 + 32
] # subtract 0x20 byte header here
with open(elf_path, "rb") as f:
elf_computed_sha256 = hashlib.sha256(f.read()).digest()
with open(bin_path, "rb") as f:
f.seek(self.SHA_OFFS)
bin_sha256_raw = f.read(len(elf_computed_sha256))
assert elf_computed_sha256 == bin_sha256
assert elf_computed_sha256 == bin_sha256_raw
def test_binary_patched_parameter(self):
try:
self.run_elf2image(
"esp32",
"esp32c6",
self.ELF,
extra_args=["--elf-sha256-offset", f"{self.SHA_OFFS:#x}"],
)
image = esptool.bin_image.LoadFirmwareImage("esp32", self.BIN)
rodata_segment = image.segments[0]
bin_sha256 = rodata_segment.data[
self.SHA_OFFS - 0x20 : self.SHA_OFFS - 0x20 + 32
] # subtract 0x20 byte header here
self.verify_sha256(self.ELF, self.BIN)
finally:
try_delete(self.BIN)
with open(self.ELF, "rb") as f:
elf_computed_sha256 = hashlib.sha256(f.read()).digest()
with open(self.BIN, "rb") as f:
f.seek(self.SHA_OFFS)
bin_sha256_raw = f.read(len(elf_computed_sha256))
assert elf_computed_sha256 == bin_sha256
assert elf_computed_sha256 == bin_sha256_raw
def test_binary_patched(self):
try:
self.run_elf2image("esp32c6", self.ELF)
self.verify_sha256(self.ELF, self.BIN)
finally:
try_delete(self.BIN)
@@ -516,3 +537,96 @@ class TestHashAppend(BaseTestCase):
assert bin_without_hash[self.HASH_APPEND_OFFSET] == 0
assert bytes(expected_bin_without_hash) == bin_without_hash
class TestMMUPageSize(BaseTestCase):
def test_appdesc_aligned(self, capsys):
ELF = "esp32c6-appdesc.elf"
BIN = "esp32c6-appdesc.bin"
try:
self.run_elf2image("esp32c6", ELF)
output = capsys.readouterr().out
print(output)
assert "MMU page size not specified, set to 64 KB" in output
finally:
try_delete(BIN)
@staticmethod
def _modify_section_address(elf_path, section_name, address_offset):
with open(elf_path, "rb+") as f:
elf = ELFFile(f)
section = elf.get_section_by_name(section_name)
if not section:
raise ValueError(f"Section {section_name} not found")
# This finds the index of the specified section in the ELF file,
# compute the section headers position in the file (using the section index,
# the section header tables offset and section header entry size) and then
# modify the sections address in memory by the specified offset.
index = elf.get_section_index(section_name)
sh_entry_offset = elf.header["e_shoff"] + index * elf.header["e_shentsize"]
section.header.sh_addr += address_offset
# Write modified header to file
f.seek(sh_entry_offset)
f.write(elf.structs.Elf_Shdr.build(section.header))
def test_appdesc_not_aligned(self, capsys):
ELF = "esp32c6-appdesc.elf"
BIN = "esp32c6-appdesc.bin"
ADDRESS_OFFSET = 4 # 4 bytes is minimum allowed
self._modify_section_address(ELF, ".flash.appdesc", ADDRESS_OFFSET)
try:
self.run_elf2image("esp32c6", ELF, allow_warnings=True)
output = capsys.readouterr().out
print(output)
assert (
"App description segment is not aligned to MMU page size, probably linker script issue or wrong MMU page size. Use --flash-mmu-page-size to set it manually."
in output
)
finally:
# Restore original address to be able to run other tests
self._modify_section_address(ELF, ".flash.appdesc", -ADDRESS_OFFSET)
try_delete(BIN)
@staticmethod
def _change_appdesc_mmu_page_size(elf_path, mmu_page_size):
"""
Change the MMU page size in the appdesc section of the ELF file.
The following values can be chosen: 0 (empty), 8192, 16384, 32768, 65536.
The numbers are not valid for all chips, so refer to the documentation of the chip being used.
"""
with open(elf_path, "rb+") as f:
elf = ELFFile(f)
section = elf.get_section_by_name(".flash.appdesc")
if not section:
raise ValueError("Section .flash.appdesc not found")
# The mmu_page_size is a power of 2, so we need to convert it to the corresponding
# value that should be written in the appdesc section. It can also be empty (0).
if mmu_page_size == 0:
mmu_page_size_appdesc = 0
else:
mmu_page_size_appdesc = int(math.log2(mmu_page_size))
# Go to the mmu_page_size in the appdesc section (which is at offset 0xB4) and change it
f.seek(section.header.sh_offset + 0xB4)
f.write(mmu_page_size_appdesc.to_bytes(4, byteorder="little"))
def test_appdesc_data(self, capsys):
ELF = "esp32c6-appdesc.elf"
BIN = "esp32c6-appdesc.bin"
MMU_PAGE_SIZE = 65536
self._change_appdesc_mmu_page_size(ELF, MMU_PAGE_SIZE)
try:
self.run_elf2image("esp32c6", ELF)
output = capsys.readouterr().out
assert "MMU page size" not in output
print(output)
finally:
self._change_appdesc_mmu_page_size(ELF, 0)
try_delete(BIN)