7
votes

My custom development board is based on x86 and one of the electronic component which is connected to it (through SPI mainly) cannot be controlled easily without using the vendor kernel driver (and the vendor won't help if I don't use it). This module requires some configuration parameters that it gets from the device tree. I believe this module is mostly used on ARM platforms where device trees are common.

On x86, the device tree is generally not needed so it is disabled by default during Linux kernel compilation. I changed the configuration in order to enable it, but I cannot find the way to put the device tree BLOB into the boot image. There is only one DTS file for the x86 architecture in the kernel sources but it doesn't seem to be used at all so it doesn't help.

From the kernel documentation, I understand I need to put it in the setup_data field of the x86 real-mode kernel header, but I don't understand how to do that and when (at kernel build time? when building the bootloader?). Am I supposed to hack the arch/x86/boot/header.S file directly?

Right now, I've replaced the module configuration by hard-coded values, but using the device tree would be better.

1
You may check OLPC and CE4100 platforms which are x86 and using Device Tree. But I suggest to consult vendor to switch to built-in device property API and use some platform code in your case. - 0andriy
support may be available in main line also, have a look here lxr.free-electrons.com/source/arch/x86/kernel/devicetree.c for arm's it is given here crashcourse.ca/wiki/index.php/Kernel_parsing_of_device_trees, may be a replica of steps can be made from the second link to first one - Samrat Das
Good to read, however maybe not so helpful in this particular case, is the following QA: stackoverflow.com/questions/46095840/…, stackoverflow.com/questions/54768841/… and stackoverflow.com/questions/39118721/… - 0andriy

1 Answers

2
votes

On x86, the boot loader adds the Device Tree binary data (DTB) to the linked list of setup_data structures before calling the kernel entry point. The DTB can be loaded from a storage device or embedded into the boot loader image.

The following code shows how it's implemented in U-Boot.

http://git.denx.de/?p=u-boot.git;a=blob;f=arch/x86/lib/zimage.c:

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;
}