From 87d1a2597ceedd03a7d4005db1bf82b72b423a18 Mon Sep 17 00:00:00 2001 From: Miquel Sabaté Solà Date: Tue, 26 Nov 2024 21:43:54 +0100 Subject: Show the detected machine model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Originally I was planning to detect the machine model just in case we needed to do workaround for special cases. But since apparently even VisionFive2 brings its own CPU frequency base on DT, this is not even needed. Hence, fetching the model is now a cool message being shown on boot. Signed-off-by: Miquel Sabaté Solà --- lib/dt.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'lib/dt.c') diff --git a/lib/dt.c b/lib/dt.c index ddf01f3..f5eed92 100644 --- a/lib/dt.c +++ b/lib/dt.c @@ -96,6 +96,54 @@ __kernel int32_t find_dt_node(uint32_t *dtb, struct fdt_header *header, const ch return (int32_t)idx; } +// Returns the index in the 'dtb' of the first proper node. +__kernel uint32_t first_dt_node(uint32_t *dtb, struct fdt_header *header) +{ + uint32_t idx; + + for (idx = header->off_dt_struct; idx < header->size_dt_struct; idx++) { + if (dtb[idx] == FDT_BEGIN_NODE_LE) { + return idx; + } + } + + return 0; +} + +// Set the 'model' buffer from 'info' if available on the 'dtb' blob. +__kernel void set_dt_model(uint32_t *dtb, struct dt_info *info, struct fdt_header *header) +{ + uint32_t len, nameoff; + uint32_t idx = first_dt_node(dtb, header); + char *base_dt_string = ((char *)dtb) + header->off_dt_string; + + while (idx < header->size_dt_struct) { + len = __bswap_constant_32(dtb[idx + 1]); + nameoff = __bswap_constant_32(dtb[idx + 2]); + idx += 3; + + if (strcmp(&base_dt_string[nameoff], "model") == 0) { + // In the (very unlikely) case that the model string is huge, don't + // even try. + if (len >= DT_MODEL_MAX) { + printk("WARNING: The model string is too large!\n"); + break; + } + + // And copy the string. Since we know the length of it, we can + // simply use 'memcpy' which is already available on kernel code as + // well. + memcpy(info->model, (char *)&dtb[idx], len); + info->model[len] = '\0'; + break; + } + + // Skip until the beginning of the next node. + for (; dtb[idx] != FDT_PROP_LE && idx < header->size_dt_struct; idx++) + ; + } +} + // Set the 'cpu_freq' field of 'info' if available on the 'dtb' blob. __kernel void set_cpu_freq(uint32_t *dtb, struct dt_info *info, struct fdt_header *header) { @@ -151,6 +199,8 @@ __kernel void get_dt_info(uint32_t *dtb, struct dt_info *info) .size_dt_struct = __bswap_constant_32(dtb[9]) / sizeof(uint32_t), }; + set_dt_model(dtb, info, &header); + set_initrd_addr(dtb, info, &header); if (!info->initrd_start || !info->initrd_end) { die("Could not fetch the addresses for the initramfs\n"); -- cgit v1.2.3