riscv64: integrate minimal flattened devicetree reader and switch timer to time CSR
Punch list §25 item 0.3 NOT complete. - Added `starkernel/fdt.h` and `fdt.c` for minimal read-only devicetree parsing: sufficient for boot-time lookups such as `timebase-frequency`. - Bootloader now captures the devicetree blob (DTB) from `EFI_DTB_TABLE_GUID` into `BootInfo::dtb`. - RISC-V timer subsystem now uses the `time` CSR as the primary timestamp source, abandoning the hardcoded `cycle` frequency assumption. - Timer rate is read from `timebase-frequency` in the DTB when accessible; otherwise, a fallback value is used with a RELATIVE trust level. - Integrated the SBI TIME extension for one-shot timer deadlines, ensuring re-arming occurs after each tick to avoid missing heartbeats. Verified: riscv64 builds clean, boots to the ok> prompt with no regression; `riscv64/timer.c` reports accurate frequencies on QEMU's default firmware. Signed-off-by: Robert Allan James <robert.allan.james@gmail.com>
This commit is contained in:
@@ -15,19 +15,25 @@
|
||||
* 16: memory_map_descriptor_size u64 (8)
|
||||
* 24: runtime_services ptr (8)
|
||||
* 32: acpi_table ptr (8)
|
||||
* 40: framebuffer FramebufferInfo (32)
|
||||
* 40: dtb ptr (8)
|
||||
* 48: framebuffer FramebufferInfo (32)
|
||||
* .base ptr (8)
|
||||
* .size u64 (8)
|
||||
* .width u32 (4)
|
||||
* .height u32 (4)
|
||||
* .pixels_per_scanline u32 (4)
|
||||
* .pixel_format u32 (4)
|
||||
* 72: uefi_boot_services_exited u8 (1)
|
||||
* 73: [7 bytes padding]
|
||||
* 80: kernel_stack_base ptr (8) ← BOOT_INFO_KERNEL_STACK_BASE_OFFSET
|
||||
* 88: kernel_stack_size u64 (8) ← BOOT_INFO_KERNEL_STACK_SIZE_OFFSET
|
||||
* 96: args KernelArgs
|
||||
* 80: uefi_boot_services_exited u8 (1)
|
||||
* 81: [7 bytes padding]
|
||||
* 88: kernel_stack_base ptr (8) ← BOOT_INFO_KERNEL_STACK_BASE_OFFSET
|
||||
* 96: kernel_stack_size u64 (8) ← BOOT_INFO_KERNEL_STACK_SIZE_OFFSET
|
||||
* 104: args KernelArgs
|
||||
*
|
||||
* 2026-08-03, punch-list item 0.3: `dtb` inserted at 40, shifting everything
|
||||
* below it by 8. The _Static_asserts in uefi_loader.c caught the stale
|
||||
* constants immediately — that is what they are for; do not silence them by
|
||||
* moving a field, fix the offsets.
|
||||
*/
|
||||
|
||||
#define BOOT_INFO_KERNEL_STACK_BASE_OFFSET 80
|
||||
#define BOOT_INFO_KERNEL_STACK_SIZE_OFFSET 88
|
||||
#define BOOT_INFO_KERNEL_STACK_BASE_OFFSET 88
|
||||
#define BOOT_INFO_KERNEL_STACK_SIZE_OFFSET 96
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
StarForth — Steady-State Virtual Machine Runtime
|
||||
Copyright (c) 2023–2025 Robert A. James. All rights reserved.
|
||||
Licensed under the StarForth License, Version 1.0.
|
||||
*/
|
||||
|
||||
/**
|
||||
* fdt.h - Minimal flattened-devicetree reader
|
||||
*
|
||||
* Just enough of the Devicetree Specification v0.4 §5 to pull values out of
|
||||
* the blob the UEFI firmware publishes under EFI_DTB_TABLE_GUID. Read-only,
|
||||
* no allocation, no tree construction — it walks the structure block each
|
||||
* call, which is fine for the handful of boot-time lookups the kernel needs.
|
||||
*
|
||||
* Deliberately not a general devicetree library. Added for punch-list item
|
||||
* 0.3 (riscv64 timebase-frequency); item 0.6 will need node-scoped `reg`
|
||||
* lookups for the aarch64 GIC and may extend this.
|
||||
*/
|
||||
|
||||
#ifndef STARKERNEL_FDT_H
|
||||
#define STARKERNEL_FDT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Test whether @p fdt points at a valid flattened devicetree.
|
||||
*
|
||||
* Checks the 0xd00dfeed magic and that the structure and strings blocks lie
|
||||
* inside totalsize. Does not validate the token stream.
|
||||
*
|
||||
* @param fdt Candidate blob; NULL is safe and returns 0.
|
||||
* @return 1 if the header is usable, 0 otherwise.
|
||||
*/
|
||||
int fdt_valid(const void* fdt);
|
||||
|
||||
/**
|
||||
* @brief Find the first property with @p name anywhere in the tree.
|
||||
*
|
||||
* Scans the structure block in document order and returns the first match
|
||||
* regardless of which node it belongs to. That is sufficient for properties
|
||||
* which are uniform across a machine (timebase-frequency being the case this
|
||||
* was written for) and is *not* sufficient for anything node-scoped.
|
||||
*
|
||||
* @param fdt Blob, already checked with @c fdt_valid().
|
||||
* @param name Property name, NUL-terminated.
|
||||
* @param len_out Receives the property length in bytes; may be NULL.
|
||||
* @return Pointer to the property value inside @p fdt, or NULL if not found.
|
||||
* The value is big-endian as stored in the blob.
|
||||
*/
|
||||
const void* fdt_find_prop(const void* fdt, const char* name, uint32_t* len_out);
|
||||
|
||||
/**
|
||||
* @brief Read a single-cell (32-bit) property by name.
|
||||
*
|
||||
* Convenience over @c fdt_find_prop() that also handles the big-endian
|
||||
* conversion. Fails if the property is absent or not exactly 4 bytes.
|
||||
*
|
||||
* @param fdt Blob, already checked with @c fdt_valid().
|
||||
* @param name Property name, NUL-terminated.
|
||||
* @param out Receives the host-order value on success; untouched on failure.
|
||||
* @return 1 on success, 0 on failure.
|
||||
*/
|
||||
int fdt_prop_u32(const void* fdt, const char* name, uint32_t* out);
|
||||
|
||||
#endif /* STARKERNEL_FDT_H */
|
||||
@@ -383,6 +383,14 @@ typedef struct {
|
||||
static const EFI_GUID EFI_ACPI_20_TABLE_GUID = {0x8868e871,0xe4f1,0x11d3,{0xbc,0x22,0x00,0x80,0xc7,0x3c,0x88,0x81}};
|
||||
static const EFI_GUID EFI_ACPI_TABLE_GUID = {0xeb9d2d30,0x2d88,0x11d3,{0x9a,0x16,0x00,0x90,0x27,0x3f,0xc1,0x4d}};
|
||||
|
||||
/* Devicetree Blob GUID (UEFI 2.10 §4.6, "Devicetree Tables").
|
||||
* On QEMU virt for riscv64 and aarch64 the firmware publishes the FDT here;
|
||||
* it is the only route to timebase-frequency (riscv64, item 0.3) and to the
|
||||
* GIC base addresses and timer PPI (aarch64, item 0.6). */
|
||||
static const EFI_GUID EFI_DTB_TABLE_GUID = {
|
||||
0xb1b621d5, 0xf19c, 0x41a5, {0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0}
|
||||
};
|
||||
|
||||
/* Graphics Output Protocol */
|
||||
typedef enum {
|
||||
PixelRedGreenBlueReserved8BitPerColor,
|
||||
@@ -627,6 +635,11 @@ typedef struct {
|
||||
UINTN memory_map_descriptor_size;
|
||||
EFI_RUNTIME_SERVICES *runtime_services;
|
||||
void *acpi_table;
|
||||
/* Devicetree blob, located by EFI_DTB_TABLE_GUID in the configuration
|
||||
* table; NULL when the firmware publishes none (amd64 typically, and any
|
||||
* platform that is ACPI-only). Consumers must handle NULL rather than
|
||||
* assume presence. */
|
||||
void* dtb;
|
||||
FramebufferInfo framebuffer;
|
||||
UINT8 uefi_boot_services_exited;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user