Skip to content

Commit 9bf7d21

Browse files
authored
Merge pull request #874 from danielinux/fenrir-fixes-2026-08-26
Fenrir fixes 2026 08 26
2 parents 626f3ab + 42a42ec commit 9bf7d21

12 files changed

Lines changed: 932 additions & 44 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,12 +492,15 @@ tools/unit-tests/nxp_ls1028a_host.c
492492
tools/unit-tests/nxp_p1021_host.c
493493
tools/unit-tests/nxp_t10xx_fixup_extract.h
494494
tools/unit-tests/sama5d3_read_extract.h
495+
tools/unit-tests/samr21_erase_extract.h
496+
tools/unit-tests/samr21_erase_fn_extract.h
495497
tools/unit-tests/sdhci_host.c
496498
tools/unit-tests/stm32l5_write_extract.h
497499
tools/unit-tests/stm32u5_write_extract.h
498500
tools/unit-tests/t10xx_qe_firmware_extract.h
499501
tools/unit-tests/t2080_fman_extract.h
500502
tools/unit-tests/ti_hercules_write_extract.h
503+
tools/unit-tests/update_trigger_scrub_extract.h
501504
tools/unit-tests/versal_ext_write_extract.h
502505
tools/unit-tests/versal_host.c
503506
tools/unit-tests/versal_host.h

hal/nxp_t10xx.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,10 +1796,13 @@ static int hal_pcie_init(void)
17961796
memset(&enum_info, 0, sizeof(enum_info));
17971797
enum_info.curr_bus_number = 0;
17981798
enum_info.mem = CONFIG_PCIE_MEM_BUS;
1799-
enum_info.mem_limit = enum_info.mem + (CONFIG_PCIE_MEM_LENGTH - 1);
1799+
/* Pool limits are exclusive ends (the allocator accepts a
1800+
* region when its end is <= limit). */
1801+
enum_info.mem_limit = (uint64_t)enum_info.mem +
1802+
CONFIG_PCIE_MEM_LENGTH;
18001803
enum_info.mem_pf = (enum_info.mem + CONFIG_PCIE_MEM_PREFETCH_LENGTH);
1801-
enum_info.mem_pf_limit = enum_info.mem_pf +
1802-
(CONFIG_PCIE_MEM_PREFETCH_LENGTH - 1);
1804+
enum_info.mem_pf_limit = (uint64_t)enum_info.mem_pf +
1805+
CONFIG_PCIE_MEM_PREFETCH_LENGTH;
18031806
enum_info.io = CONFIG_PCIE_IO_BASE;
18041807

18051808
/* Setup PCIe Output Windows */

hal/samr21.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
#define FLASH_SIZE (256 * 1024)
4040
#define FLASH_PAGESIZE 64
4141
#define FLASH_N_PAGES 4096
42+
/* NVMCMD_ERASE (0x02) is the NVMCTRL row erase: one command erases a
43+
* 256-byte row (4 pages), so erase loops stride by the row size. */
44+
#define FLASH_ROW_SIZE (4 * FLASH_PAGESIZE)
4245

4346
#define WDT_CTRL *((volatile uint8_t *)(0x40001000))
4447
#define WDT_EN (1 << 1)
@@ -210,8 +213,9 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
210213
while (len > 0) {
211214
NVMCTRL_ADDR = (address >> 1); /* This register holds the address of a 16-bit row */
212215
NVMCTRLA_REG = NVMCMD_ERASE | NVMCMD_KEY;
213-
while(!(NVMCTRL_INTFLAG & NVMCTRL_INTFLAG_NVMREADY))
214-
len -= FLASH_PAGESIZE;
216+
while (!(NVMCTRL_INTFLAG & NVMCTRL_INTFLAG_NVMREADY)) { }
217+
address += FLASH_ROW_SIZE;
218+
len -= FLASH_ROW_SIZE;
215219
}
216220
return 0;
217221
}

include/pci.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,15 @@ typedef struct {
8989
} pci_ctrlr_info_t;
9090

9191
struct pci_enum_info {
92-
uint32_t mem;
93-
uint32_t mem_limit;
94-
uint32_t io;
95-
uint32_t mem_pf;
96-
uint32_t mem_pf_limit;
92+
/* Allocation cursors and exclusive pool ends. All 64-bit: a pool
93+
* may end exactly at 4 GiB (0x100000000), which a 32-bit value
94+
* cannot represent, and an exhausted cursor must stay at the pool
95+
* end instead of wrapping to 0 and re-allocating over address 0. */
96+
uint64_t mem;
97+
uint64_t mem_limit;
98+
uint64_t io;
99+
uint64_t mem_pf;
100+
uint64_t mem_pf_limit;
97101
uint8_t curr_bus_number;
98102
};
99103

src/libwolfboot.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,11 @@ void RAMFUNCTION wolfBoot_update_trigger(void)
914914
/* erase the previously selected sector */
915915
hal_flash_erase(lastSector - WOLFBOOT_SECTOR_SIZE * selSec,
916916
WOLFBOOT_SECTOR_SIZE);
917+
/* The staged sector may hold the firmware key/nonce (see
918+
* ENCRYPT_CACHE under NVM_FLASH_WRITEONCE): scrub it, as the
919+
* partition-trailer helpers do, before releasing the flash
920+
* lock. */
921+
nvm_cache_scrub();
917922
#endif
918923
}
919924

src/pci.c

Lines changed: 57 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -100,18 +100,18 @@
100100
static int pci_enum_is_64bit(uint32_t value);
101101
static int pci_enum_is_mmio(uint32_t value);
102102

103-
static inline uint32_t align_up(uint32_t address, uint32_t alignment) {
104-
return (address + alignment - 1) & ~(alignment - 1);
103+
static inline uint64_t align_up(uint64_t address, uint32_t alignment) {
104+
return (address + alignment - 1) & ~(uint64_t)(alignment - 1);
105105
}
106106

107107
static inline uint32_t align_down(uint32_t address, uint32_t alignment) {
108108
return address & ~(alignment - 1);
109109
}
110110

111-
static int pci_align_check_up(uint32_t address, uint32_t alignment,
112-
uint32_t limit, uint32_t *aligned)
111+
static int pci_align_check_up(uint64_t address, uint32_t alignment,
112+
uint64_t limit, uint64_t *aligned)
113113
{
114-
uint32_t a;
114+
uint64_t a;
115115
a = align_up(address, alignment);
116116
if (a < address || a >= limit)
117117
return -1;
@@ -363,17 +363,20 @@ static int pci_enum_is_mmio(uint32_t value)
363363
return (value & PCI_ENUM_MMIND_MASK) == 0;
364364
}
365365

366-
static int pci_enum_next_aligned32(uint32_t address, uint32_t *next,
367-
uint32_t align, uint32_t limit)
366+
static int pci_enum_next_aligned32(uint64_t address, uint32_t *next,
367+
uint32_t align, uint64_t limit)
368368
{
369-
uintptr_t addr;
369+
uint64_t addr;
370370

371-
addr = (uintptr_t)address;
371+
/* 64-bit on purpose: an exhausted pool leaves the cursor at
372+
* 0x100000000, which a 32-bit type (uintptr_t included on 32-bit
373+
* targets) would truncate back to 0. */
374+
addr = address;
372375
align = align-1;
373-
addr = (addr + align) & (~align);
376+
addr = (addr + align) & (~(uint64_t)align);
374377
if (addr > 0xffffffff)
375378
return -1;
376-
if (addr < (uintptr_t)address)
379+
if (addr < address)
377380
return -1;
378381
if (addr >= limit)
379382
return -1;
@@ -421,8 +424,8 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun,
421424
uint32_t length, align;
422425
uint8_t bar_off;
423426
int is_prefetch;
424-
uint32_t *base;
425-
uint32_t limit;
427+
uint64_t *base;
428+
uint64_t limit;
426429
uint32_t reg;
427430
int is_mmio;
428431
int ret = 0;
@@ -524,7 +527,7 @@ static int pci_program_bar(uint8_t bus, uint8_t dev, uint8_t fun,
524527
pci_config_write32(bus, dev, fun, bar_off, bar_value);
525528
if (*is_64bit)
526529
pci_config_write32(bus, dev, fun, bar_off + 4, 0x0);
527-
*base = bar_value + length;
530+
*base = (uint64_t)bar_value + length;
528531
PCI_DEBUG_PRINTF("PCI enum: %s bus: %x:%x.%x bar: %d [%x,%x] (0x%x %s %s)\r\n",
529532
(is_mmio ? "mm" : "io"), bus, dev, fun, bar_idx, bar_value,
530533
bar_value + length, length, (*is_64bit) ? "64bit" : "",
@@ -617,14 +620,14 @@ static inline void pci_dump_bridge(uint8_t bus, uint8_t dev, uint8_t fun)
617620
static int pci_program_bridge(uint8_t bus, uint8_t dev, uint8_t fun,
618621
struct pci_enum_info *info)
619622
{
620-
uint32_t prefetch_start;
621-
uint32_t mem_start;
622-
uint32_t io_start;
623+
uint64_t prefetch_start;
624+
uint64_t mem_start;
625+
uint64_t io_start;
623626
uint32_t orig_cmd;
624627
uint8_t saved_bus;
625-
uint32_t saved_mem;
626-
uint32_t saved_pf;
627-
uint32_t saved_io;
628+
uint64_t saved_mem;
629+
uint64_t saved_pf;
630+
uint64_t saved_io;
628631
int ret;
629632

630633
saved_bus = info->curr_bus_number;
@@ -635,6 +638,13 @@ static int pci_program_bridge(uint8_t bus, uint8_t dev, uint8_t fun,
635638
orig_cmd = pci_config_read16(bus, dev, fun, PCI_COMMAND_OFFSET);
636639
pci_config_write16(bus, dev, fun, PCI_COMMAND_OFFSET, 0);
637640

641+
/* curr_bus_number is one bus per bridge level; at 0xFF the next
642+
* increment wraps to 0, which would write SECONDARY_BUS 0 and
643+
* re-enumerate bus 0 over the already configured tree. Disable
644+
* this bridge instead. */
645+
if (info->curr_bus_number == 0xFF)
646+
goto err;
647+
638648
info->curr_bus_number++;
639649
PCI_DEBUG_PRINTF("Bridge: %x.%x.%x (using bus number: %d)\r\n",
640650
(int)bus, (int)dev, (int)fun, info->curr_bus_number);
@@ -926,11 +936,28 @@ int pci_enum_do(void)
926936
struct pci_enum_info enum_info;
927937
int ret;
928938

939+
/* Pool limits are exclusive ends: the allocator accepts a region
940+
* when its end is <= limit (pci_enum_next_aligned32, the BAR end
941+
* check, pci_align_check_up) and the IO limit is the 16-bit IO
942+
* ceiling, not the last usable address. A region ending exactly
943+
* at base + length must fit, so initialize base + length. The
944+
* limit fields are 64-bit because a pool may end exactly at
945+
* 0x100000000 (4 GiB), the top of the 32-bit space; reject only
946+
* pools whose end is above it. */
947+
if ((uint64_t)PCI_MMIO32_BASE + PCI_MMIO32_LENGTH > 0x100000000ULL ||
948+
(uint64_t)PCI_MMIO32_PREFETCH_BASE +
949+
PCI_MMIO32_PREFETCH_LENGTH > 0x100000000ULL)
950+
{
951+
PCI_DEBUG_PRINTF("PCI MMIO pool overflows the 32-bit address "
952+
"space\r\n");
953+
return -1;
954+
}
955+
929956
enum_info.mem = PCI_MMIO32_BASE;
930-
enum_info.mem_limit = enum_info.mem + (PCI_MMIO32_LENGTH - 1);
957+
enum_info.mem_limit = (uint64_t)enum_info.mem + PCI_MMIO32_LENGTH;
931958
enum_info.mem_pf = PCI_MMIO32_PREFETCH_BASE;
932-
enum_info.mem_pf_limit = enum_info.mem_pf +
933-
(PCI_MMIO32_PREFETCH_LENGTH - 1);
959+
enum_info.mem_pf_limit = (uint64_t)enum_info.mem_pf +
960+
PCI_MMIO32_PREFETCH_LENGTH;
934961
enum_info.io = PCI_IO32_BASE;
935962
enum_info.curr_bus_number = 0;
936963

@@ -943,16 +970,17 @@ int pci_enum_do(void)
943970
ret = pci_enum_bus(0, &enum_info);
944971

945972
PCI_DEBUG_PRINTF("PCI Memory Mapped I/O range [0x%x,0x%x] (0x%x)\r\n",
946-
(uint32_t)PCI_MMIO32_BASE, enum_info.mem,
947-
enum_info.mem - PCI_MMIO32_BASE);
973+
(uint32_t)PCI_MMIO32_BASE, (uint32_t)enum_info.mem,
974+
(uint32_t)(enum_info.mem - PCI_MMIO32_BASE));
948975

949976
PCI_DEBUG_PRINTF("PCI Memory Mapped I/O range (prefetch) [0x%x,0x%x] (0x%x)\r\n",
950-
(uint32_t)PCI_MMIO32_PREFETCH_BASE, enum_info.mem_pf,
951-
enum_info.mem_pf - PCI_MMIO32_PREFETCH_BASE);
977+
(uint32_t)PCI_MMIO32_PREFETCH_BASE,
978+
(uint32_t)enum_info.mem_pf,
979+
(uint32_t)(enum_info.mem_pf - PCI_MMIO32_PREFETCH_BASE));
952980

953981
PCI_DEBUG_PRINTF("PCI I/O range [0x%x,0x%x] (0x%x)\r\n",
954-
(uint32_t)PCI_IO32_BASE, enum_info.io,
955-
enum_info.io - PCI_IO32_BASE);
982+
(uint32_t)PCI_IO32_BASE, (uint32_t)enum_info.io,
983+
(uint32_t)(enum_info.io - PCI_IO32_BASE));
956984

957985
return ret;
958986
}

src/sdhci.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,13 @@ static int sdcard_card_init(uint32_t acmd41_arg, uint32_t *ocr_reg)
829829
static int sdcard_set_bus_width(uint32_t bus_width);
830830
static int sdcard_set_function(uint32_t function_number, uint32_t group_number);
831831

832+
/* A card that answers ACMD41 forever without setting OCR ready must
833+
* not hold the boot. The budget matches the sdhci_wait_busy() wait;
834+
* a healthy card reports ready in milliseconds. */
835+
#ifndef SDCARD_ACMD41_TIMEOUT_MS
836+
#define SDCARD_ACMD41_TIMEOUT_MS 30000
837+
#endif
838+
832839
/* Full SD card initialization sequence
833840
* Returns 0 on success */
834841
static int sdcard_card_full_init(void)
@@ -898,6 +905,9 @@ static int sdcard_card_full_init(void)
898905
}
899906

900907
if (status == 0) {
908+
uint64_t start = hal_get_timer_us();
909+
const uint64_t timeout_us =
910+
(uint64_t)SDCARD_ACMD41_TIMEOUT_MS * 1000U;
901911
/* configure operating conditions */
902912
uint32_t cmd_arg = SDCARD_ACMD41_HCS;
903913
cmd_arg |= card_volts;
@@ -911,10 +921,17 @@ static int sdcard_card_full_init(void)
911921
wolfBoot_printf("sdcard_init: sending OCR arg: 0x%08X\n", cmd_arg);
912922
#endif
913923

914-
/* retry until OCR ready */
924+
/* retry until OCR ready; a card that never sets it must not
925+
* hold the boot, so bound the poll like sdhci_wait_busy() and
926+
* service the watchdog inside it */
915927
do {
916928
status = sdcard_card_init(cmd_arg, &reg);
917-
} while (status == 0 && (reg & SDCARD_REG_OCR_READY) == 0);
929+
if (status != 0 || (reg & SDCARD_REG_OCR_READY) != 0)
930+
break;
931+
sdhci_platform_wdt_pet();
932+
if (hal_get_timer_us() - start > timeout_us)
933+
status = -1;
934+
} while (status == 0);
918935
}
919936

920937
if (status == 0) {

0 commit comments

Comments
 (0)