Linux kernel 如何将设备树blob添加到Linux x86内核引导?

Linux kernel 如何将设备树blob添加到Linux x86内核引导?,linux-kernel,x86,embedded-linux,bootloader,device-tree,Linux Kernel,X86,Embedded Linux,Bootloader,Device Tree,我的定制开发板基于x86,其中一个连接到它的电子组件(主要通过SPI)如果不使用供应商的内核驱动程序就无法轻松控制(如果我不使用它,供应商也不会提供帮助)。此模块需要从设备树获取一些配置参数。我相信这个模块主要用于ARM平台,在这些平台上,设备树很常见 在x86上,通常不需要设备树,因此在Linux内核编译期间,默认情况下会禁用设备树。我更改了配置以启用它,但是我找不到将设备树BLOB放入引导映像的方法。内核源代码中只有针对x86体系结构的代码,但它似乎根本没有被使用,因此没有任何帮助 从中,我

我的定制开发板基于x86,其中一个连接到它的电子组件(主要通过SPI)如果不使用供应商的内核驱动程序就无法轻松控制(如果我不使用它,供应商也不会提供帮助)。此模块需要从设备树获取一些配置参数。我相信这个模块主要用于ARM平台,在这些平台上,设备树很常见

在x86上,通常不需要设备树,因此在Linux内核编译期间,默认情况下会禁用设备树。我更改了配置以启用它,但是我找不到将设备树BLOB放入引导映像的方法。内核源代码中只有针对x86体系结构的代码,但它似乎根本没有被使用,因此没有任何帮助

从中,我了解到我需要将它放入的
设置\u数据
字段中,但我不了解如何做以及何时做(在内核构建时?在构建引导加载程序时?)。我应该直接破解文件吗


现在,我已经用硬编码值替换了模块配置,但是使用设备树会更好。

在x86上,引导加载程序在调用内核入口点之前将设备树二进制数据(DTB)添加到设置数据结构的链接列表中。DTB可以从存储设备加载,也可以嵌入到引导加载程序映像中

下面的代码显示了它是如何在U-Boot中实现的

:

static int setup\u device\u树(结构setup\u头*hdr,const void*fdt\u blob)
{
int bootproto=get_boot_协议(hdr);
结构设置_数据*sd;
整数大小;
如果(bootproto<0x0209)
返回-ENOTSUPP;
如果(!fdt_blob)
返回0;
尺寸=fdt_总尺寸(fdt_blob);
如果(尺寸<0)
返回-艾因瓦尔;
size+=sizeof(结构设置数据);
sd=(结构设置_数据*)malloc(大小);
如果(!sd){
printf(“没有足够的内存用于DTB设置数据\n”);
return-ENOMEM;
}
sd->next=hdr->setup\U数据;
sd->type=设置\u DTB;
sd->len=fdt\u总尺寸(fdt\u blob);
memcpy(sd->data,fdt_blob,sd->len);
hdr->setup_data=(无符号长)sd;
返回0;
}

您可以检查OLPC和CE4100平台,它们是x86,并且使用设备树。但我建议咨询供应商,切换到内置设备属性API,并在您的案例中使用一些平台代码。主线中也可能提供支持,请查看此处提供的arm,可能是步骤的副本,可以从第二个链接复制到第一个链接,很好阅读,但在这种特殊情况下可能没有太大帮助,以下是QA:,和@ignorinov感谢您的回答。你知道有哪种x86引导加载程序允许这样做,并且支持通过BIOS加载(u-boot不支持这种方式)?@Tey':欢迎你。根据doc/README.x86,它支持通过BIOS加载:“U-Boot支持作为32位或64位EFI有效负载启动,例如使用UEFI。这是通过配置EFI存根启用的,可以从32位和64位UEFI BIOS启动。U-Boot也可以作为EFI应用程序运行,使用配置EFI应用程序。我猜我的术语有误导性:通过“BIOS”,我指的是传统BIOS(不是UEFI)。要从传统BIOS加载U-Boot,需要编写第一阶段加载程序(类似于GRUB的第1阶段),从存储设备的连续块加载U-Boot,并使用传统BIOS调用将其复制到首选地址。GRUB也支持devicetree,但我不确定它是否能在x86上工作:Intel Edison使用U-Boot作为链式引导加载程序,它完全满足了@Tey的要求。
static int setup_device_tree(struct setup_header *hdr, const void *fdt_blob)
{
        int bootproto = get_boot_protocol(hdr);
        struct setup_data *sd;
        int size;

        if (bootproto < 0x0209)
                return -ENOTSUPP;

        if (!fdt_blob)
                return 0;

        size = fdt_totalsize(fdt_blob);
        if (size < 0)
                return -EINVAL;

        size += sizeof(struct setup_data);
        sd = (struct setup_data *)malloc(size);
        if (!sd) {
                printf("Not enough memory for DTB setup data\n");
                return -ENOMEM;
        }

        sd->next = hdr->setup_data;
        sd->type = SETUP_DTB;
        sd->len = fdt_totalsize(fdt_blob);
        memcpy(sd->data, fdt_blob, sd->len);
        hdr->setup_data = (unsigned long)sd;

        return 0;
}