Building the section

Two basic calls in the startup library are used to add things to the hwinfo section:

void *hwi_alloc_tag(const char *name, unsigned size, unsigned align);

This call allocates a tag of size size with the tag name of name. If the structure contains any 64-bit integer fields within it, the align field should be set to 8; otherwise, it should be 4. The function returns a pointer to memory that can be filled in as appropriate. Note that the hwi_prefix fields are automatically filled in by the hwi_alloc_tag() function.

void *hwi_alloc_item(const char *name, unsigned size, 
                     unsigned align, const char *itemname,
                     unsigned owner);

This call allocates an item structure. The first three parameters are the same as in the hwi_alloc_tag() function.

The itemname and owner parameters are used to set the itemname and owner fields of the hwi_item structure. All hwi_alloc_tag() calls done after a hwi_alloc_item() call are assumed to belong to that item and the itemsize field is adjusted appropriately.

Here are the general steps for building an item:

  1. Call hwi_alloc_item() to build a top-level item (one with the owner field to be HWI_NULL_OFF).
  2. Add whatever other tag structures you want in the item.
  3. Use hwi_alloc_item() to start a new item. This item could be either another top-level one or a child of the first.

Note that you can build the items in any order you wish, provided that the parent is built before the child.

When building a child item, suppose you've remembered its owner in a variable or you know only its item name. In order to find out the correct value of the owner parameter, you can use the hwi_find_item() function (which is defined in the C library, since it's useful for people processing the section):

unsigned hwi_find_item(unsigned start, ...);

The start parameter indicates where to start the search for the given item. For an initial call, it should be set to HWI_NULL_OFF. If the item found isn't the one wanted, then the return value from the first hwi_find_item() is used as the start parameter of the second call. The search will pick up where it left off. This can be repeated as many times as required (the return value from the second call going into the start parameter of the third, etc). The item being searched is identified by a sequence of char * parameters following start. The sequence is terminated by a NULL. The last string before the NULL is the bottom-level itemname being searched for, the string in front of that is the name of the item that owns the bottom-level item, etc.

For example, this call finds the first occurrence of an item called "foobar":

item_off = hwi_find_item(HWI_NULL_OFF, "foobar", NULL);

The following call finds the first occurrence of an item called "foobar" that's owned by "sam":

item_off = hwi_find_item(HWI_NULL_OFF, "sam", "foobar", NULL);

If the requested item can't be found, HWI_NULL_OFF is returned.