Re: How to properly locate/parse ACPI table from kernel module?
- In reply to: John Nielsen : "Re: How to properly locate/parse ACPI table from kernel module?"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 20 May 2021 18:45:22 UTC
On 21. 5. 20., John Nielsen wrote: >> On May 19, 2021, at 9:41 PM, John Nielsen <lists@jnielsen.net >> <mailto:lists@jnielsen.net>> wrote: >> >>> On May 19, 2021, at 12:21 PM, Jung-uk Kim <jkim@freebsd.org >>> <mailto:jkim@freebsd.org>> wrote: >>> >>> On 21. 5. 19., Jung-uk Kim wrote: >>>> On 21. 5. 19., John Nielsen wrote: >>>>>> On May 17, 2021, at 2:27 PM, Jung-uk Kim <junguk.kim@gmail.com >>>>>> <mailto:junguk.kim@gmail.com>> wrote: >>>>>> >>>>>> On 21. 5. 17., John Nielsen wrote: >>>>>>> I’m not much of a kernel programmer but I’m trying to >>>>>>> maintain/improve the isboot module, which allows booting directly >>>>>>> from iSCSI by reading the iSCSI Boot Firmware Table (iBFT), >>>>>>> bringing up the interface with the details specified therein and >>>>>>> connecting to the specified iSCSI target before trying to mount root. >>>>>>> >>>>>>> I’m not the original author but as the port maintainer I am >>>>>>> hosting the code here: https://github.com/jnielsendotnet/isboot >>>>>>> <https://github.com/jnielsendotnet/isboot> >>>>>>> >>>>>>> I have a test system where the module loads but fails to find the >>>>>>> iBFT. I reviewed the iBFT code and realized it has a bunch of >>>>>>> magic numbers mixed in with some random memory diving. If I’m >>>>>>> reading it right (see >>>>>>> https://github.com/jnielsendotnet/isboot/blob/master/src/ibft.h#L37 >>>>>>> <https://github.com/jnielsendotnet/isboot/blob/master/src/ibft.h#L37> >>>>>>> and >>>>>>> https://github.com/jnielsendotnet/isboot/blob/master/src/ibft.c#L521 >>>>>>> <https://github.com/jnielsendotnet/isboot/blob/master/src/ibft.c#L521>), >>>>>>> it looks like it scans all of the (kernel?) memory between 512K >>>>>>> and 1M in 16-byte increments looking for one beginning with the >>>>>>> string “iBFT”, which if it finds will be used as the offset for >>>>>>> reading the table. I don’t know where the 512K and 1M values came >>>>>>> from or if they are correct, but I do have a system where that >>>>>>> method does not work. >>>>>>> >>>>>>> IIUC, the iBFT is an ACPI table, and it seems like using ACPI to >>>>>>> find it would be safer and more reliable. So my question is: how >>>>>>> does one do that? Are there other places in the kernel code that >>>>>>> do this sort of thing that I could use as a model? Any gotchas I >>>>>>> should know about as a (less-than) novice kernel programmer? >>>>>> >>>>>> You may use AcpiGetTable() and AcpiPutTable(), e.g., >>>>>> >>>>>> status = AcpiGetTable(ACPI_SIG_IBFT, …); >>>>> >>>>> Thank you (and Andriy) for your responses. Good to know that >>>>> ACPI_SIG_IBFT is already defined in the upstream headers. >>>> >>>> It seems there are two methods. >>>> >>>> ftp://ftp.software.ibm.com/systems/support/bladecenter/iscsi_boot_firmware_table_v1.03.pdf >>>> <ftp://ftp.software.ibm.com/systems/support/bladecenter/iscsi_boot_firmware_table_v1.03.pdf> >>>> >>>> 1.4.3.1 Locating the iBFT >>>> >>>> The iBFT is located by the following methods. A platform shall implement >>>> one or more of these methods. >>>> >>>> 1. The ACPI Method. The iBFT is pointed to by an entry in the RSDT/XSDT. >>>> Note that ACPI [ACPI=3.0b] specifies the string in the pointer as >>>> “IBFT” (all upper case) HOWEVER the signature in the table being pointed >>>> to is“iBFT” (note the mixed case). >>>> >>>> 2. The Low RAM Method. Scan for the table header signature in system >>>> memory between 512K and 1024K. The scan MUST be done starting at >>>> the lower address scanning forward to the higher address. When using the >>>> Low RAM Method the table header must be aligned on a 16-byte >>>> boundary. >>>> >>>> Note: A system operating in UEFI mode shall utilize only the ACPI >>>> method. >>>> >>>> For modern system, it seems you should be using Method 1. I don't >>>> understand the "HOWEVER" part, though. >>> >>> I did little more research. It seems iSCSI spec. predates ACPI >>> standardization and IBM kept on using "iBFT" instead of ACPI spec. >>> "IBFT". Because this confusion, some systems use "iBFT" and some use >>> "IBFT". Therefore, it seems you need to test both, e.g., >>> >>> status = AcpiGetTable(ACPI_SIG_IBFT, 0, &ibft); >>> if (ACPI_FAILURE(status)) >>> status = AcpiGetTable("iBFT", 0, &ibft); >> >> Very helpful once again, thank you. My test machine (either the >> motherboard or the NIC) has a buggy BIOS that prevents it from booting >> in legacy mode with iSCSI so I’m using UEFI whether I wanted to or >> not. I’m glad that my theory that the Low RAM Method might not work in >> UEFI has some merit. >> >> I did notice that Linux looks for both iBFT and IBFT in its driver; >> the existence of two standards is alluded to in the comments but it’s >> nice to know what they are. I’ll adopt your suggested approach. > > In case anyone is actually following along at home, here’s what I have > so far: > https://github.com/jnielsendotnet/isboot/commit/255a01102c345347dece1ed15bd8675fe3dd1dd9 > <https://github.com/jnielsendotnet/isboot/commit/255a01102c345347dece1ed15bd8675fe3dd1dd9> > > Which not only compiles but also finds (and is able to correctly decode) > the iBFT on my test system. Hooray! Good to hear it. > Comments on the patch welcome. Otherwise I’ll move on to the next issue… You don't need to define USE_ACPI. It should be spelled "DEV_ACPI", e.g., #ifndef DEV_ACPI > Thank you again for the help thus far. Glad to help. Jung-uk Kim