From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.90_1) id 1mSl5R-0006Zn-Tu for mharc-grub-devel@gnu.org; Tue, 21 Sep 2021 15:05:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57230) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mSl5Q-0006Xs-RV for grub-devel@gnu.org; Tue, 21 Sep 2021 15:05:48 -0400 Received: from mail-ed1-x535.google.com ([2a00:1450:4864:20::535]:46903) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1mSl5O-0004eV-Cl for grub-devel@gnu.org; Tue, 21 Sep 2021 15:05:48 -0400 Received: by mail-ed1-x535.google.com with SMTP id ee50so151067edb.13 for ; Tue, 21 Sep 2021 12:05:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :content-transfer-encoding; bh=PeCnnIpKE5cQ2a/qFdzt7Zy3vejZaAp88kz+XHHJksk=; b=Ohqa46vBIwwC58InIL2r5UdcjQX8/Gx3xqgrtEkMVYkQjqsD92IeK5V1DGEobbfKY6 gW2mcHuiX1cXOqFMV9FDGTsnJQuquACwy2nbzkYWnECG68A0SAiB8n1VzdEyOm3uslFx XxqkHk6N5IkE43R9YEJGYin7SQLukDCm4+eglA5AKKpkqv2eDIEkLMgtyn6qhOUspw2a XWgbbmeEeuuNRPYwF/7BpRRPLUhlu3x8CGoDLNhBFnkWM425+Iei4RZpH9o/IxBiHoJn SoU6u2YCZ8ajJNHtBm5AgJgY2jFCN918y8sgDw5S/Ikjw35TVUAAhlX7TeAL8sdYcTFZ JRjA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:content-transfer-encoding; bh=PeCnnIpKE5cQ2a/qFdzt7Zy3vejZaAp88kz+XHHJksk=; b=GL44RWWOjnM4yFTKMF0f0bJLaQoV9kJ+HesT/ijdBw6H1mkBxk2qk72Tyi9xCILj+R TbHMOiacMng6iF1HAs7aNRwEraheh9dFtHNPRk+mnPDcmARe1ZaaWLUlNR+VTpufs/wV a8VMbgg5e0wmYVfS/A3824siO8E9ApxtlLZlTiprkJi1CVpoQtkM8cYD7p+dZKPjmijL TvgxmMG+duyZSVpqB75bXDT4e238KMTJhBBQPe22WIkZY1x6qH1hkuyUyQI5b61b/aCg uqBywYG/YP1atpRrtEnjkFh8QCz6dBuk+5emwl17cpqj9ybe8l5NVlbk4yX/NWbQhct0 PSlg== X-Gm-Message-State: AOAM533ZScdq3ZsbvNC6mn4wwspO0r4HfjJyCpsv6KqJ1JUm3qEiq/Kk sp6Ko4UotdblymZ3EzIlkMEPVSCA/s+NhV4KwIOM2oNt7bU= X-Google-Smtp-Source: ABdhPJyhYgBiFRmnJYpM4ZCCam0hCN+YXiqUtFKjIrV7fEAkO934xxtq2EQWcBtSj0GJUqo6+DhIWCqT1GUJ7+8I2Ec= X-Received: by 2002:a05:6402:1ac5:: with SMTP id ba5mr37684788edb.20.1632251143775; Tue, 21 Sep 2021 12:05:43 -0700 (PDT) MIME-Version: 1.0 References: <6DF2B90AE826754EAEE52A5F86D6E41C787D78CF@mail.xylon.local> In-Reply-To: <6DF2B90AE826754EAEE52A5F86D6E41C787D78CF@mail.xylon.local> From: "Vladimir 'phcoder' Serbinenko" Date: Tue, 21 Sep 2021 21:05:31 +0200 Message-ID: Subject: Re: [PATCH] loader/i386/linux: Add device tree support To: The development of GNU GRUB Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass client-ip=2a00:1450:4864:20::535; envelope-from=phcoder@gmail.com; helo=mail-ed1-x535.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 21 Sep 2021 19:05:49 -0000 On Tue, Sep 21, 2021 at 5:44 PM Mislav Stubli=C4=87 wrote: > > Hi, > > This implements device tree support for x86. Unfortunately I haven't been= able to test this on latest master but I have tested against 2.04 and it w= orks fine. I will test on master later but I wanted to get some initial com= ments if this is going in the right direction. What I haven't tested is fir= mware DTB loading support which only calls grub_efi_get_firmware_fdt from k= ern/efi implementation as I don't have hardware to test this scenario. > > Mislav > > Signed-off-by: Mislav Stubli=C4=87 > --- > grub-core/Makefile.am | 1 + > grub-core/Makefile.core.def | 2 + > grub-core/loader/i386/linux.c | 159 ++++++++++++++++++++++++++++++++++++= ++++-- > include/grub/efi/efi.h | 5 +- > include/grub/i386/linux.h | 21 +++++- > 5 files changed, 181 insertions(+), 7 deletions(-) > > diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am > index ee88e44..1b9ba1f 100644 > --- a/grub-core/Makefile.am > +++ b/grub-core/Makefile.am > @@ -186,6 +186,7 @@ KERNEL_HEADER_FILES +=3D $(top_srcdir)/include/grub/i= 386/tsc.h > KERNEL_HEADER_FILES +=3D $(top_srcdir)/include/grub/pci.h > KERNEL_HEADER_FILES +=3D $(top_srcdir)/include/grub/acpi.h > KERNEL_HEADER_FILES +=3D $(top_srcdir)/include/grub/i386/pmtimer.h > +KERNEL_HEADER_FILES +=3D $(top_srcdir)/include/grub/fdt.h > endif > > if COND_ia64_efi > diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def > index 8022e1c..e499057 100644 > --- a/grub-core/Makefile.core.def > +++ b/grub-core/Makefile.core.def > @@ -227,7 +227,9 @@ kernel =3D { > x86_64_xen =3D kern/x86_64/dl.c; > x86_64_efi =3D kern/x86_64/efi/callwrap.S; > x86_64_efi =3D kern/i386/efi/init.c; > + x86_64_efi =3D kern/efi/fdt.c; > x86_64_efi =3D bus/pci.c; > + x86_64_efi =3D lib/fdt.c; Any reason to put it into kernel rather than enabling fdt module on x86? > > xen =3D kern/i386/tsc.c; > xen =3D kern/i386/xen/tsc.c; > diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.= c > index 9f74a96..9c67a54 100644 > --- a/grub-core/loader/i386/linux.c > +++ b/grub-core/loader/i386/linux.c > @@ -37,6 +37,7 @@ > #include > #include > #include > +#include > > GRUB_MOD_LICENSE ("GPLv3+"); > > @@ -77,6 +78,7 @@ static void *efi_mmap_buf; > static grub_size_t maximal_cmdline_size; > static struct linux_kernel_params linux_params; > static char *linux_cmdline; > +static void *current_fdt =3D NULL; > #ifdef GRUB_MACHINE_EFI > static grub_efi_uintn_t efi_mmap_size; > #else > @@ -398,6 +400,38 @@ grub_linux_boot_mmap_fill (grub_uint64_t addr, grub_= uint64_t size, > return 0; > } > > +struct grub_fdt_ctx > +{ > + grub_addr_t fdt_target; > + grub_memory_type_t mem_type; > +}; > + > +static int > +grub_linux_boot_acpi_find (grub_uint64_t addr, grub_uint64_t size, > + grub_memory_type_t type, void *data) > +{ > + struct grub_fdt_ctx *fdt_ctx =3D data; > + grub_uint64_t fdt_size =3D grub_fdt_get_totalsize(current_fdt); > + grub_uint64_t setup_data_header =3D sizeof(struct linux_i386_kernel_he= ader_setup_data); > + > + > + if (type !=3D fdt_ctx->mem_type) > + return 0; > + > + if (size < setup_data_header + fdt_size) > + return 0; > + > + grub_dprintf ("fdt", "addr =3D 0x%lx, size =3D 0x%x, need_size =3D 0x%= x, type =3D %d\n", > + (unsigned long) addr, > + (unsigned) size, > + (unsigned) setup_data_header + fdt_size, > + fdt_ctx->mem_type); > + > + fdt_ctx->fdt_target =3D addr; > + > + return 1; > +} > + > static grub_err_t > grub_linux_boot (void) > { > @@ -411,6 +445,10 @@ grub_linux_boot (void) > }; > grub_size_t mmap_size; > grub_size_t cl_offset; > + struct grub_fdt_ctx fdt_ctx =3D {0}; > + grub_uint64_t target_setup_data; > + struct linux_i386_kernel_header_setup_data *tmp_setup_data; > + grub_size_t fdt_size; > > #ifdef GRUB_MACHINE_IEEE1275 > { > @@ -579,6 +617,57 @@ grub_linux_boot (void) > return grub_errno; > ctx.params->mmap_size =3D ctx.e820_num; > > + if (current_fdt) > + { > + fdt_ctx.mem_type =3D GRUB_MEMORY_ACPI; > +#ifdef GRUB_MACHINE_EFI > + grub_efi_mmap_iterate (grub_linux_boot_acpi_find, &fdt_ctx, 0); > +#else > + grub_mmap_iterate (grub_linux_boot_acpi_find, &fdt_ctx); > +#endif > + if (!fdt_ctx.fdt_target) > + { > + fdt_ctx.mem_type =3D GRUB_MEMORY_NVS; > +#ifdef GRUB_MACHINE_EFI > + grub_efi_mmap_iterate (grub_linux_boot_acpi_find, &fdt_ctx, 0)= ; > +#else > + grub_mmap_iterate (grub_linux_boot_acpi_find, &fdt_ctx); > +#endif > + } > + } > + > + if (fdt_ctx.fdt_target) > + { > + grub_relocator_chunk_t ch; > + > + fdt_size =3D grub_fdt_get_totalsize (current_fdt); > + > + err =3D grub_relocator_alloc_chunk_addr (relocator, &ch, > + fdt_ctx.fdt_target, > + sizeof(*tmp_setup_data) + > + fdt_size); > + if (!err) > + { > + tmp_setup_data =3D grub_zalloc (sizeof (*tmp_setup_data) + fdt= _size); > + if (tmp_setup_data) > + { > + target_setup_data =3D get_virtual_current_address (ch); > + tmp_setup_data->next =3D 0; > + tmp_setup_data->type =3D GRUB_SETUP_DTB; > + tmp_setup_data->len =3D fdt_size; > + grub_memcpy (tmp_setup_data->data, current_fdt, fdt_size); > + grub_memcpy (target_setup_data, tmp_setup_data, > + sizeof (*tmp_setup_data) + fdt_size); > + > + /* finalize FDT kernel target */ > + ctx.params->setup_data =3D target_setup_data; > + > + grub_free (tmp_setup_data); > + grub_free (current_fdt); > + } > + } > + } > + > #ifdef GRUB_MACHINE_EFI > { > grub_efi_uintn_t efi_desc_size; > @@ -591,9 +680,9 @@ grub_linux_boot (void) > &efi_desc_size, &efi_desc_versio= n); > if (err) > return err; > - > + Please don't include empty line changes > /* Note that no boot services are available from here. */ > - efi_mmap_target =3D ctx.real_mode_target > + efi_mmap_target =3D ctx.real_mode_target > + ((grub_uint8_t *) efi_mmap_buf - (grub_uint8_t *) real_mode_mem)= ; > /* Pass EFI parameters. */ > if (grub_le_to_cpu16 (ctx.params->version) >=3D 0x0208) > @@ -743,7 +832,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((un= used)), > align =3D 0; > relocatable =3D 0; > } > - > + > if (grub_le_to_cpu16 (lh.version) >=3D 0x020a) > { > min_align =3D lh.min_alignment; > @@ -1123,7 +1212,66 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ = ((unused)), > return grub_errno; > } > > -static grub_command_t cmd_linux, cmd_initrd; > +static grub_err_t > +grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)), > + int argc, char *argv[]) > +{ > + grub_file_t dtb; > + void *new_fdt; > + int size; > + > + if (current_fdt) > + grub_free (current_fdt); > + current_fdt =3D NULL; > + > +#ifdef GRUB_MACHINE_EFI > + /* no dtb file, try firmware */ > + if (argc =3D=3D 0) > + { > + current_fdt =3D grub_efi_get_firmware_fdt(); You may want to have an implementation than always returns NULL on other platforms > + if (current_fdt) > + return GRUB_ERR_NONE; > + > + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("firmware dtb not fou= nd")); > + } > +#endif > + > + if (argc !=3D 1) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("dtb filename expected"= )); > + > + dtb =3D grub_file_open (argv[0], GRUB_FILE_TYPE_DEVICE_TREE_IMAGE); > + if (!dtb) > + return grub_errno; > + > + size =3D grub_file_size (dtb); > + new_fdt =3D grub_zalloc (size); > + if (!new_fdt) > + return grub_errno; > + > + grub_dprintf ("loader", "Loading device tree to %p\n", > + new_fdt); > + if (grub_file_read (dtb, new_fdt, size) < size) > + { > + grub_free (new_fdt); > + return grub_error (GRUB_ERR_FILE_READ_ERROR, > + N_("unable to read dtb file %s"), > + argv[0]); > + } > + > + if (grub_fdt_check_header (new_fdt, size) !=3D 0) > + { > + grub_free (new_fdt); > + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("invalid device tree= ")); > + } > + > + current_fdt =3D new_fdt; > + > + grub_file_close (dtb); > + > + return grub_errno; > +} > + > +static grub_command_t cmd_linux, cmd_initrd, cmd_devicetree; > > GRUB_MOD_INIT(linux) > { > @@ -1131,6 +1279,9 @@ GRUB_MOD_INIT(linux) > 0, N_("Load Linux.")); > cmd_initrd =3D grub_register_command ("initrd", grub_cmd_initrd, > 0, N_("Load initrd.")); > + cmd_devicetree =3D grub_register_command_lockdown ("devicetree", grub_= cmd_devicetree, > + /* TRANSLATORS: DTB st= ands for device tree blob. */ > + 0, N_("Load DTB file."= )); Please use the same sentence as in another loaders > my_mod =3D mod; > } > > diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h > index 83d958f..a095925 100644 > --- a/include/grub/efi/efi.h > +++ b/include/grub/efi/efi.h > @@ -96,8 +96,11 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_e= fi_handle_t hnd, > char **device, > char **path); > > -#if defined(__arm__) || defined(__aarch64__) || defined(__riscv) > +#if defined(__arm__) || defined(__aarch64__) || defined(__riscv) || defi= ned(__x86_64__) > void *EXPORT_FUNC(grub_efi_get_firmware_fdt)(void); > +#endif > + > +#if defined(__arm__) || defined(__aarch64__) || defined(__riscv) > grub_err_t EXPORT_FUNC(grub_efi_get_ram_base)(grub_addr_t *); > #include > grub_err_t grub_arch_efi_linux_check_image(struct linux_arch_kernel_head= er *lh); > diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h > index eddf925..b66413d 100644 > --- a/include/grub/i386/linux.h > +++ b/include/grub/i386/linux.h > @@ -84,6 +84,23 @@ struct grub_e820_mmap > grub_uint32_t type; > } GRUB_PACKED; > > +/* taken from linux kernel bootparam.h */ > +#define GRUB_SETUP_NONE 0 > +#define GRUB_SETUP_E820_EXT 1 > +#define GRUB_SETUP_DTB 2 > +#define GRUB_SETUP_PCI 3 > +#define GRUB_SETUP_EFI 4 > +#define GRUB_SETUP_APPLE_PROPERTIES 5 > +#define GRUB_SETUP_JAILHOUSE 6 > +#define GRUB_SETUP_INDIRECT (1<<31) > + > +struct linux_i386_kernel_header_setup_data { > + grub_uint64_t next; > + grub_uint32_t type; > + grub_uint32_t len; > + grub_uint8_t data[0]; > +}; > + > enum > { > GRUB_VIDEO_LINUX_TYPE_TEXT =3D 0x01, > @@ -134,7 +151,7 @@ struct linux_i386_kernel_header > grub_uint16_t heap_end_ptr; /* Free memory after setup end */ > grub_uint16_t pad1; /* Unused */ > grub_uint32_t cmd_line_ptr; /* Points to the kernel command l= ine */ > - grub_uint32_t initrd_addr_max; /* Highest address for initrd */ > + grub_uint32_t initrd_addr_max; /* Highest address for initrd */ > grub_uint32_t kernel_alignment; > grub_uint8_t relocatable; > grub_uint8_t min_alignment; > @@ -144,7 +161,7 @@ struct linux_i386_kernel_header > grub_uint64_t hardware_subarch_data; > grub_uint32_t payload_offset; > grub_uint32_t payload_length; > - grub_uint64_t setup_data; > + grub_uint64_t setup_data; /* linked list of additional boot= parameters (E820, DTB, PCI)*/ > grub_uint64_t pref_address; > grub_uint32_t init_size; > grub_uint32_t handover_offset; > -- > 1.8.3.1 > > > ----- Disclaimer ----- > This e-mail message and its attachments may contain privileged and/or con= fidential information. Please do not read the message if You are not its de= signated recipient. If You have received this message by mistake, please in= form its sender and destroy the original message and its attachments withou= t reading or storing of any kind. Any unauthorized use, distribution, repro= duction or publication of this message is forbidden. > > ----- Pravne napomene ----- > Ova elektronicka poruka i njeni prilozi mogu sadrzavati povlastene inform= acije i/ili povjerljive informacije. Molimo Vas da poruku ne citate ako nis= te njen naznaceni primatelj. Ako ste ovu poruku primili greskom, molimo Vas= da o tome obavijestite posiljatelja i da izvornu poruku i njene privitke u= nistite bez citanja ili bilo kakvog pohranjivanja. Svaka neovlastena upotre= ba, distribucija, reprodukcija ili priopcavanje ove poruke zabranjena je. > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > https://lists.gnu.org/mailman/listinfo/grub-devel --=20 Regards Vladimir 'phcoder' Serbinenko