fix(console): the serial line is found, not assumed -- from the devicetree on a board, COM1 by probe on a PC
Each board has one serial line that is its console, the lowest common denominator beside the screen and keyboard. Its address was QEMU's, fixed: on a Raspberry Pi 5 the aarch64 one is ordinary RAM, written to with every character printed; on a Milk-V Mars the riscv64 one is the board's UART with registers four bytes apart, and the UEFI loader would have waited for ever on its first character; on a PC with no COM1 the prompt read 0xFF for ever. console_attach_serial(), called before anything prints: COM1 if a UART answers there; elsewhere the UART that /chosen/stdout-path names (fdt_uart.c: alias, path, the address carried up through each bus's ranges, reg-shift and reg-io-width); with no devicetree, QEMU's. A devicetree that names no usable console gives no line, not a guess. A line that does not come ready is given up, not waited on. The riscv64 loader's early serial does the same. tools/fdt_uart_test.c, run by hand, 19 checks plain and under the sanitizers: devicetrees shaped like the Mars's, the Pi 5's and QEMU's, what must find nothing, and a block cut short at every length; and the Pi 5's real devicetree gives a PL011 at 0x107d001000. Acceptance, one QEMU at a time: v3 on amd64 (logs/20261013-204436), aarch64 (-204803) and riscv64 (-205001) to the zuse prompt, no unknown word, hash 0x08873e0f44b7cb2a on all three as before. -204600 is an aarch64 run during which the disk images were restored under it by a script that had been refused a second QEMU; it passed and is kept, and was run again. v4 on the three ISAs (-211149, -211444, -211857): POST 538 of 538, dict_hash 0xe5a57f3eb72ff94a, the typed session unchanged. The Mars image through OpenSBI and U-Boot in QEMU took its line and its interrupt controller from the devicetree and passed POST. Found on the way and not mended (boards/BRINGUP.md 1.6): built with EMERGENCY_CONSOLE_ENABLED=1 the prompt floods with empty lines. -210442 shows it; the commit before this does the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f4e359859a
commit
c95191736e
@@ -506,6 +506,106 @@ const void* fdt_next_child_node(const void* fdt, const void* parent,
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
int fdt_complete(const void* fdt)
|
||||
{
|
||||
const fdt_header_t* h = (const fdt_header_t*)fdt;
|
||||
uint32_t size_struct;
|
||||
|
||||
if (!fdt_valid(fdt)) return 0;
|
||||
size_struct = be32(&h->size_dt_struct);
|
||||
if (size_struct < 4 || (size_struct & 3u)) return 0;
|
||||
return be32((const unsigned char*)fdt + be32(&h->off_dt_struct) + size_struct - 4) == FDT_END;
|
||||
}
|
||||
|
||||
const void* fdt_root_node(const void* fdt)
|
||||
{
|
||||
const fdt_header_t* h = (const fdt_header_t*)fdt;
|
||||
const unsigned char *p, *end;
|
||||
|
||||
if (!fdt_valid(fdt)) return (void*)0;
|
||||
|
||||
p = (const unsigned char*)fdt + be32(&h->off_dt_struct);
|
||||
end = p + be32(&h->size_dt_struct);
|
||||
|
||||
while (p + 4 <= end)
|
||||
{
|
||||
uint32_t token = be32(p);
|
||||
p += 4;
|
||||
|
||||
if (token == FDT_NOP) continue;
|
||||
if (token != FDT_BEGIN_NODE) break;
|
||||
|
||||
{
|
||||
const unsigned char* q = p;
|
||||
while (q < end && *q) q++;
|
||||
if (q >= end) break;
|
||||
return (const void*)(((uintptr_t)(q + 1) + 3u) & ~(uintptr_t)3u);
|
||||
}
|
||||
}
|
||||
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
const void* fdt_find_child(const void* fdt, const void* parent,
|
||||
const char* name, uint32_t name_len)
|
||||
{
|
||||
const fdt_header_t* h = (const fdt_header_t*)fdt;
|
||||
const unsigned char *end, *p;
|
||||
|
||||
if (!fdt_valid(fdt) || !parent || !name) return (void*)0;
|
||||
|
||||
end = (const unsigned char*)fdt + be32(&h->off_dt_struct) + be32(&h->size_dt_struct);
|
||||
p = (const unsigned char*)parent;
|
||||
|
||||
/* parent's own properties first, then its children one after another:
|
||||
* each child that is not the one wanted is skipped whole. */
|
||||
while (p + 4 <= end)
|
||||
{
|
||||
uint32_t token = be32(p);
|
||||
p += 4;
|
||||
|
||||
if (token == FDT_BEGIN_NODE)
|
||||
{
|
||||
const unsigned char* q = p;
|
||||
const unsigned char* body;
|
||||
uint32_t i;
|
||||
|
||||
while (q < end && *q) q++;
|
||||
if (q >= end) return (void*)0;
|
||||
body = (const unsigned char*)(((uintptr_t)(q + 1) + 3u) & ~(uintptr_t)3u);
|
||||
|
||||
/* the whole name, unit address and all, and nothing more */
|
||||
if ((uint32_t)(q - p) == name_len)
|
||||
{
|
||||
for (i = 0; i < name_len && p[i] == (unsigned char)name[i]; i++) { }
|
||||
if (i == name_len) return (const void*)body;
|
||||
}
|
||||
p = skip_node_body(body, end);
|
||||
}
|
||||
else if (token == FDT_PROP)
|
||||
{
|
||||
uint32_t len;
|
||||
|
||||
if (p + 8 > end) break;
|
||||
len = be32(p);
|
||||
p += 8;
|
||||
if (len > (uint32_t)(end - p)) break;
|
||||
p = (const unsigned char*)(((uintptr_t)(p + len) + 3u) & ~(uintptr_t)3u);
|
||||
}
|
||||
else if (token == FDT_NOP)
|
||||
{
|
||||
/* no payload */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FDT_END_NODE (parent closing), FDT_END, or unknown */
|
||||
return (void*)0;
|
||||
}
|
||||
}
|
||||
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
const void* fdt_find_prop_in_node(const void* fdt, const void* node,
|
||||
const char* name, uint32_t* len_out)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user