iPXE discussion forum
Help me understand iPXE code - Printable Version

+- iPXE discussion forum (https://forum.ipxe.org)
+-- Forum: iPXE user forums (/forumdisplay.php?fid=1)
+--- Forum: General (/forumdisplay.php?fid=2)
+--- Thread: Help me understand iPXE code (/showthread.php?tid=6912)



Help me understand iPXE code - Rickert - 2013-05-15 11:24

In main.c, it calls initialize() and startup(). Inside each of these functions, it loops through table that contains the registered functions and calls them:

Code:
void startup ( void ) {
    struct startup_fn *startup_fn;

    if ( started )
        return;

    /* Call registered startup functions */
    for_each_table_entry ( startup_fn, STARTUP_FNS ) {
        if ( startup_fn->startup )
            startup_fn->startup();
    }

    started = 1;
}

I don't know where the registered functions are.

STARTUP_FNS:

Code:
#define STARTUP_FNS __table ( struct startup_fn, "startup_fns" )

__table:

Code:
#define __table( type, name ) ( type, name )

__table is the end of what I can look into. The comment says that it "Declare a linker table". But how can it get the functions?

Please help. I really want to understand. Thanks.


RE: Help me understand iPXE code - mcb30 - 2013-05-15 23:45

(2013-05-15 11:24)Rickert Wrote:  __table is the end of what I can look into. The comment says that it "Declare a linker table". But how can it get the functions?

I answered this same question in http://stackoverflow.com/questions/16562864/how-ipxe-executes-functions-without-calling-its-names/16564674#16564674; posting here for the record:

The linker script instructs the linker to arrange sections ".tbl.*" in alphabetical order. The __table_entry etc macros are used to place structures into these sections. The easiest way to understand this is probably to look at the linker map, which you can produce using e.g. "make bin/rtl8139.rom.map":

Code:
.tbl.init_fns.00
            0x000000000001784c        0x0 bin/blib.a(init.o)
.tbl.init_fns.01
            0x000000000001784c        0x4 bin/blib.a(malloc.o)
            0x000000000001784c                heap_init_fn
.tbl.init_fns.04
            0x0000000000017850        0x4 bin/blib.a(pxe_call.o)
            0x0000000000017850                pxe_init_fn
.tbl.init_fns.04
            0x0000000000017854        0x4 bin/blib.a(settings.o)
            0x0000000000017854                builtin_init_fn
.tbl.init_fns.04
            0x0000000000017858        0x4 bin/blib.a(smbios_settings.o)
            0x0000000000017858                smbios_init_fn
.tbl.init_fns.04
            0x000000000001785c        0x4 bin/blib.a(process.o)
            0x000000000001785c                process_init_fn
.tbl.init_fns.05
            0x0000000000017860        0x4 bin/blib.a(embedded.o)
            0x0000000000017860                embedded_init_fn
.tbl.init_fns.99
            0x0000000000017864        0x0 bin/blib.a(init.o)

Here you can see the various structures (heap_init_fn, pxe_init_fn, smbios_init_fn) etc. have been placed consecutively in the final image, sorted by initialisation order (01=INIT_EARLY, used for heap_init_fn in malloc.c; 04=INIT_NORMAL, used for smbios_init_fn in smbios_settings.c etc).

The __table_start and __table_end macros in init.c produce zero-length arrays placed in .tbl.init_fns.00 and .tbl.init_fns.99; these can then be used by the code in init.c to identify the start and end of the table that has been constructed by the linker.

Hope that helps!

Michael


RE: Help me understand iPXE code - Rickert - 2013-05-16 08:34

Thanks Micheal,

I have a few more questions regard of this technique:
  • What's this technique called?
  • How to generate a similar table and use it in my code? Are the table names auto-generated or declared?
  • What's the reason for doing this? Isn't it easier to create an array of function pointers?

I would really appreciate if you provide relevant resources for studying more of this process.

Thanks again.


RE: Help me understand iPXE code - mcb30 - 2013-05-16 10:09

(2013-05-16 08:34)Rickert Wrote:  
  • What's this technique called?
  • How to generate a similar table and use it in my code? Are the table names auto-generated or declared?
  • What's the reason for doing this? Isn't it easier to create an array of function pointers?

I'm not aware of this technique having a name. It's something I created, inspired by the way that the old Etherboot code handled the PCI driver list. The concept of vector-valued macros as used in tables.h is, as far as I am aware, an original idea.

If your code is licensed under GPL then you can include iPXE's tables.h directly. You can see examples of how to declare a specific table in e.g. init.h, and examples of how to declare table entries in any file containing e.g. __startup_fn. The only other part you'll need is the linker script directive to keep all table entries and sort them alphabetically:

Code:
KEEP(*(SORT(.tbl.*)))

The reason for doing this is that allows the contents of the array to be determined at link time rather than compile time. For example, both bin/realtek.rom and bin/intel.rom can be generated from the exact same compiled code simply by adjusting the options passed to the linker. Using an array of function pointers would require something like:

Code:
struct pci_driver * pci_drivers[] = {
#ifdef REALTEK
  &realtek_driver,
#endif
#ifdef INTEL
  &intel_driver,
#endif
#ifdef ....
  ....
  ....
#endif
}

See http://dox.ipxe.org/ifdef_harmful.html for some more detailed background.

Michael


RE: Help me understand iPXE code - Rickert - 2013-05-17 08:33

Thanks, Micheal. I read the document and learned something useful.

Another thing that's bugging me is the written DHCP code (my dhcp problem is solved, until now). There exists functions for handling dhcp creating and requesting DHCP packets: dhcp_create_packet / dhcp_create_request. When the dhcp command is executed from the script, iPXE did call those two functions (I put printf inside those functions). Yet, I found no function calling those functions in the iIPXE source code, not even the linker table.

Could you help me find the missing link here?


RE: Help me understand iPXE code - mcb30 - 2013-05-20 07:00

(2013-05-17 08:33)Rickert Wrote:  Another thing that's bugging me is the written DHCP code (my dhcp problem is solved, until now). There exists functions for handling dhcp creating and requesting DHCP packets: dhcp_create_packet / dhcp_create_request. When the dhcp command is executed from the script, iPXE did call those two functions (I put printf inside those functions). Yet, I found no function calling those functions in the iIPXE source code, not even the linker table.

Try

Code:
git grep -E 'dhcp_create_packet|dhcp_create_request'

That will show you all the references to these functions within the source code.

Michael