iPXE
Functions | Variables
efi_snp_hii.c File Reference

EFI SNP HII protocol. More...

#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <errno.h>
#include <ipxe/settings.h>
#include <ipxe/nvo.h>
#include <ipxe/device.h>
#include <ipxe/netdevice.h>
#include <ipxe/version.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_hii.h>
#include <ipxe/efi/efi_snp.h>
#include <ipxe/efi/efi_strings.h>
#include <ipxe/efi/efi_utils.h>
#include <config/branding.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 EFI_REQUEST_PROTOCOL (EFI_HII_DATABASE_PROTOCOL,&efihii)
static struct settingsefi_snp_hii_settings (struct efi_snp_device *snpdev)
 Identify settings to be exposed via HII.
static int efi_snp_hii_setting_applies (struct efi_snp_device *snpdev, struct setting *setting)
 Check whether or not setting is applicable.
static void efi_snp_hii_random_guid (EFI_GUID *guid)
 Generate a random GUID.
static void efi_snp_hii_questions (struct efi_snp_device *snpdev, struct efi_ifr_builder *ifr, unsigned int varstore_id)
 Generate EFI SNP questions.
static
EFI_HII_PACKAGE_LIST_HEADER
efi_snp_hii_package_list (struct efi_snp_device *snpdev)
 Build HII package list for SNP device.
static int efi_snp_hii_append (struct efi_snp_device *snpdev __unused, const char *key, const char *value, wchar_t **results)
 Append response to result string.
static int efi_snp_hii_fetch (struct efi_snp_device *snpdev, const char *key, const char *value, wchar_t **results, int *have_setting)
 Fetch HII setting.
static int efi_snp_hii_store (struct efi_snp_device *snpdev, const char *key, const char *value, wchar_t **results __unused, int *have_setting __unused)
 Fetch HII setting.
static int efi_snp_hii_process (struct efi_snp_device *snpdev, wchar_t *string, wchar_t **progress, wchar_t **results, int *have_setting, int(*process)(struct efi_snp_device *, const char *key, const char *value, wchar_t **results, int *have_setting))
 Process portion of HII configuration string.
static EFI_STATUS EFIAPI efi_snp_hii_extract_config (const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, EFI_STRING request, EFI_STRING *progress, EFI_STRING *results)
 Fetch configuration.
static EFI_STATUS EFIAPI efi_snp_hii_route_config (const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, EFI_STRING config, EFI_STRING *progress)
 Store configuration.
static EFI_STATUS EFIAPI efi_snp_hii_callback (const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, EFI_BROWSER_ACTION action __unused, EFI_QUESTION_ID question_id __unused, UINT8 type __unused, EFI_IFR_TYPE_VALUE *value __unused, EFI_BROWSER_ACTION_REQUEST *action_request __unused)
 Handle form actions.
int efi_snp_hii_install (struct efi_snp_device *snpdev)
 Install HII protocol and packages for SNP device.
void efi_snp_hii_uninstall (struct efi_snp_device *snpdev)
 Uninstall HII protocol and package for SNP device.

Variables

static EFI_GUID efi_hii_platform_setup_formset_guid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID
 EFI platform setup formset GUID.
static EFI_GUID efi_hii_ibm_ucm_compliant_formset_guid = EFI_HII_IBM_UCM_COMPLIANT_FORMSET_GUID
 EFI IBM UCM compliant formset GUID.
static EFI_HII_DATABASE_PROTOCOLefihii
 EFI HII database protocol.
static
EFI_HII_CONFIG_ACCESS_PROTOCOL 
efi_snp_device_hii
 HII configuration access protocol.

Detailed Description

EFI SNP HII protocol.

The HII protocols are some of the less-well designed parts of the entire EFI specification. This is a significant accomplishment.

The face-slappingly ludicrous query string syntax seems to be motivated by the desire to allow a caller to query multiple drivers simultaneously via the single-instance HII_CONFIG_ROUTING_PROTOCOL, which is supposed to pass relevant subsets of the query string to the relevant drivers.

Nobody uses the HII_CONFIG_ROUTING_PROTOCOL. Not even the EFI setup browser uses the HII_CONFIG_ROUTING_PROTOCOL. To the best of my knowledge, there has only ever been one implementation of the HII_CONFIG_ROUTING_PROTOCOL (as part of EDK2), and it just doesn't work. It's so badly broken that I can't even figure out what the code is _trying_ to do.

Fundamentally, the problem seems to be that Javascript programmers should not be allowed to design APIs for C code.

Definition in file efi_snp_hii.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static struct settings* efi_snp_hii_settings ( struct efi_snp_device snpdev) [static, read]

Identify settings to be exposed via HII.

Parameters:
snpdevSNP device
Return values:
settingsSettings, or NULL

Definition at line 87 of file efi_snp_hii.c.

References find_child_settings(), efi_snp_device::netdev, netdev_settings(), and NVO_SETTINGS_NAME.

Referenced by efi_snp_hii_fetch(), efi_snp_hii_setting_applies(), and efi_snp_hii_store().

static int efi_snp_hii_setting_applies ( struct efi_snp_device snpdev,
struct setting setting 
) [static]

Check whether or not setting is applicable.

Parameters:
snpdevSNP device
settingSetting
Return values:
appliesSetting applies

Definition at line 100 of file efi_snp_hii.c.

References efi_snp_hii_settings(), and nvo_applies().

Referenced by efi_snp_hii_extract_config(), and efi_snp_hii_questions().

                                                                   {

        return nvo_applies ( efi_snp_hii_settings ( snpdev ), setting );
}
static void efi_snp_hii_random_guid ( EFI_GUID guid) [static]

Generate a random GUID.

Parameters:
guidGUID to fill in

Definition at line 111 of file efi_snp_hii.c.

References byte, and random().

Referenced by efi_snp_hii_install(), and efi_snp_hii_package_list().

                                                       {
        uint8_t *byte = ( ( uint8_t * ) guid );
        unsigned int i;

        for ( i = 0 ; i < sizeof ( *guid ) ; i++ )
                *(byte++) = random();
}
static void efi_snp_hii_questions ( struct efi_snp_device snpdev,
struct efi_ifr_builder ifr,
unsigned int  varstore_id 
) [static]

Generate EFI SNP questions.

Parameters:
snpdevSNP device
ifrIFR builder
varstore_idVariable store identifier

Definition at line 126 of file efi_snp_hii.c.

References setting::description, efi_ifr_string(), efi_ifr_string_op(), efi_snp_hii_setting_applies(), for_each_table_entry, setting::name, NULL, PRODUCT_SETTING_URI, setting_cmp(), SETTINGS, and setting::tag.

Referenced by efi_snp_hii_package_list().

                                                               {
        struct setting *setting;
        struct setting *previous = NULL;
        unsigned int name_id;
        unsigned int prompt_id;
        unsigned int help_id;
        unsigned int question_id;

        /* Add all applicable settings */
        for_each_table_entry ( setting, SETTINGS ) {
                if ( ! efi_snp_hii_setting_applies ( snpdev, setting ) )
                        continue;
                if ( previous && ( setting_cmp ( setting, previous ) == 0 ) )
                        continue;
                previous = setting;
                name_id = efi_ifr_string ( ifr, "%s", setting->name );
                prompt_id = efi_ifr_string ( ifr, "%s", setting->description );
                help_id = efi_ifr_string ( ifr, PRODUCT_SETTING_URI,
                                           setting->name );
                question_id = setting->tag;
                efi_ifr_string_op ( ifr, prompt_id, help_id,
                                    question_id, varstore_id, name_id,
                                    0, 0x00, 0xff, 0 );
        }
}

Build HII package list for SNP device.

Parameters:
snpdevSNP device
Return values:
packagePackage list, or NULL on error

Definition at line 161 of file efi_snp_hii.c.

References DBGC, net_device::dev, device::driver_name, efi_hii_ibm_ucm_compliant_formset_guid, efi_hii_platform_setup_formset_guid, efi_ifr_end_op(), efi_ifr_form_op(), efi_ifr_form_set_op(), efi_ifr_free(), efi_ifr_guid_class_op(), efi_ifr_guid_subclass_op(), efi_ifr_init(), efi_ifr_string(), efi_ifr_text_op(), efi_ifr_varstore_name_value_op(), EFI_NETWORK_DEVICE_CLASS, efi_snp_hii_questions(), efi_snp_hii_random_guid(), device::name, name, efi_snp_device::netdev, netdev, netdev_addr(), NULL, product_name, product_short_name, product_version, and efi_ifr_builder::varstore_id.

Referenced by efi_snp_hii_install().

                                                           {
        struct net_device *netdev = snpdev->netdev;
        struct device *dev = netdev->dev;
        struct efi_ifr_builder ifr;
        EFI_HII_PACKAGE_LIST_HEADER *package;
        const char *name;
        EFI_GUID package_guid;
        EFI_GUID formset_guid;
        EFI_GUID varstore_guid;
        unsigned int title_id;
        unsigned int varstore_id;

        /* Initialise IFR builder */
        efi_ifr_init ( &ifr );

        /* Determine product name */
        name = ( product_name[0] ? product_name : product_short_name );

        /* Generate GUIDs */
        efi_snp_hii_random_guid ( &package_guid );
        efi_snp_hii_random_guid ( &formset_guid );
        efi_snp_hii_random_guid ( &varstore_guid );

        /* Generate title string (used more than once) */
        title_id = efi_ifr_string ( &ifr, "%s (%s)", name,
                                    netdev_addr ( netdev ) );

        /* Generate opcodes */
        efi_ifr_form_set_op ( &ifr, &formset_guid, title_id,
                              efi_ifr_string ( &ifr, "Configure %s",
                                               product_short_name ),
                              &efi_hii_platform_setup_formset_guid,
                              &efi_hii_ibm_ucm_compliant_formset_guid, NULL );
        efi_ifr_guid_class_op ( &ifr, EFI_NETWORK_DEVICE_CLASS );
        efi_ifr_guid_subclass_op ( &ifr, 0x03 );
        varstore_id = efi_ifr_varstore_name_value_op ( &ifr, &varstore_guid );
        efi_ifr_form_op ( &ifr, title_id );
        efi_ifr_text_op ( &ifr,
                          efi_ifr_string ( &ifr, "Name" ),
                          efi_ifr_string ( &ifr, "Firmware product name" ),
                          efi_ifr_string ( &ifr, "%s", name ) );
        efi_ifr_text_op ( &ifr,
                          efi_ifr_string ( &ifr, "Version" ),
                          efi_ifr_string ( &ifr, "Firmware version" ),
                          efi_ifr_string ( &ifr, "%s", product_version ) );
        efi_ifr_text_op ( &ifr,
                          efi_ifr_string ( &ifr, "Driver" ),
                          efi_ifr_string ( &ifr, "Firmware driver" ),
                          efi_ifr_string ( &ifr, "%s", dev->driver_name ) );
        efi_ifr_text_op ( &ifr,
                          efi_ifr_string ( &ifr, "Device" ),
                          efi_ifr_string ( &ifr, "Hardware device" ),
                          efi_ifr_string ( &ifr, "%s", dev->name ) );
        efi_snp_hii_questions ( snpdev, &ifr, varstore_id );
        efi_ifr_end_op ( &ifr );
        efi_ifr_end_op ( &ifr );

        /* Build package */
        package = efi_ifr_package ( &ifr, &package_guid, "en-us",
                                    efi_ifr_string ( &ifr, "English" ) );
        if ( ! package ) {
                DBGC ( snpdev, "SNPDEV %p could not build IFR package\n",
                       snpdev );
                efi_ifr_free ( &ifr );
                return NULL;
        }

        /* Free temporary storage */
        efi_ifr_free ( &ifr );
        return package;
}
static int efi_snp_hii_append ( struct efi_snp_device *snpdev  __unused,
const char *  key,
const char *  value,
wchar_t **  results 
) [static]

Append response to result string.

Parameters:
snpdevSNP device
keyKey
valueValue
resultsResult string
Return values:
rcReturn status code

The result string is allocated dynamically using BootServices::AllocatePool(), and the caller is responsible for eventually calling BootServices::FreePool().

Definition at line 246 of file efi_snp_hii.c.

References EFI_BOOT_SERVICES::AllocatePool, EFI_SYSTEM_TABLE::BootServices, efi_snprintf(), efi_systab, EfiBootServicesData, ENOMEM, EFI_BOOT_SERVICES::FreePool, len, strlen(), and wcslen().

Referenced by efi_snp_hii_fetch().

                                                    {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        size_t len;
        void *new;

        /* Allocate new string */
        len = ( ( *results ? ( wcslen ( *results ) + 1 /* "&" */ ) : 0 ) +
                strlen ( key ) + 1 /* "=" */ + strlen ( value ) + 1 /* NUL */ );
        bs->AllocatePool ( EfiBootServicesData, ( len * sizeof ( wchar_t ) ),
                           &new );
        if ( ! new )
                return -ENOMEM;

        /* Populate string */
        efi_snprintf ( new, len, "%ls%s%s=%s", ( *results ? *results : L"" ),
                       ( *results ? L"&" : L"" ), key, value );
        bs->FreePool ( *results );
        *results = new;

        return 0;
}
static int efi_snp_hii_fetch ( struct efi_snp_device snpdev,
const char *  key,
const char *  value,
wchar_t **  results,
int *  have_setting 
) [static]

Fetch HII setting.

Parameters:
snpdevSNP device
keyKey
valueValue
resultsResult string
have_settingFlag indicating detection of a setting
Return values:
rcReturn status code

Definition at line 280 of file efi_snp_hii.c.

References DBGC, efi_snp_hii_append(), efi_snp_hii_settings(), ENODEV, ENOMEM, ENOTSUP, fetchf_setting(), find_setting(), free, len, setting::name, NULL, origin, rc, setting_exists(), sprintf, strcasecmp(), strerror(), and zalloc().

Referenced by efi_snp_hii_extract_config().

                                                                      {
        struct settings *settings = efi_snp_hii_settings ( snpdev );
        struct settings *origin;
        struct setting *setting;
        struct setting fetched;
        int len;
        char *buf;
        char *encoded;
        int i;
        int rc;

        /* Handle ConfigHdr components */
        if ( ( strcasecmp ( key, "GUID" ) == 0 ) ||
             ( strcasecmp ( key, "NAME" ) == 0 ) ||
             ( strcasecmp ( key, "PATH" ) == 0 ) ) {
                return efi_snp_hii_append ( snpdev, key, value, results );
        }
        if ( have_setting )
                *have_setting = 1;

        /* Do nothing more unless we have a settings block */
        if ( ! settings ) {
                rc = -ENOTSUP;
                goto err_no_settings;
        }

        /* Identify setting */
        setting = find_setting ( key );
        if ( ! setting ) {
                DBGC ( snpdev, "SNPDEV %p no such setting \"%s\"\n",
                       snpdev, key );
                rc = -ENODEV;
                goto err_find_setting;
        }

        /* Encode value */
        if ( setting_exists ( settings, setting ) ) {

                /* Calculate formatted length */
                len = fetchf_setting ( settings, setting, &origin, &fetched,
                                       NULL, 0 );
                if ( len < 0 ) {
                        rc = len;
                        DBGC ( snpdev, "SNPDEV %p could not fetch %s: %s\n",
                               snpdev, setting->name, strerror ( rc ) );
                        goto err_fetchf_len;
                }

                /* Allocate buffer for formatted value and HII-encoded value */
                buf = zalloc ( len + 1 /* NUL */ + ( len * 4 ) + 1 /* NUL */ );
                if ( ! buf ) {
                        rc = -ENOMEM;
                        goto err_alloc;
                }
                encoded = ( buf + len + 1 /* NUL */ );

                /* Format value */
                fetchf_setting ( origin, &fetched, NULL, NULL, buf,
                                 ( len + 1 /* NUL */ ) );
                for ( i = 0 ; i < len ; i++ ) {
                        sprintf ( ( encoded + ( 4 * i ) ), "%04x",
                                  *( ( uint8_t * ) buf + i ) );
                }

        } else {

                /* Non-existent or inapplicable setting */
                buf = NULL;
                encoded = "";
        }

        /* Append results */
        if ( ( rc = efi_snp_hii_append ( snpdev, key, encoded,
                                         results ) ) != 0 ) {
                goto err_append;
        }

        /* Success */
        rc = 0;

 err_append:
        free ( buf );
 err_alloc:
 err_fetchf_len:
 err_find_setting:
 err_no_settings:
        return rc;
}
static int efi_snp_hii_store ( struct efi_snp_device snpdev,
const char *  key,
const char *  value,
wchar_t **results  __unused,
int *have_setting  __unused 
) [static]

Fetch HII setting.

Parameters:
snpdevSNP device
keyKey
valueValue
resultsResult string (unused)
have_settingFlag indicating detection of a setting (unused)
Return values:
rcReturn status code

Definition at line 381 of file efi_snp_hii.c.

References DBGC, efi_snp_hii_settings(), EINVAL, ENODEV, ENOMEM, ENOTSUP, find_setting(), free, len, memcpy(), setting::name, rc, storef_setting(), strcasecmp(), strerror(), strlen(), strtoul(), and zalloc().

Referenced by efi_snp_hii_route_config().

                                                            {
        struct settings *settings = efi_snp_hii_settings ( snpdev );
        struct setting *setting;
        char *buf;
        char tmp[5];
        char *endp;
        int len;
        int i;
        int rc;

        /* Handle ConfigHdr components */
        if ( ( strcasecmp ( key, "GUID" ) == 0 ) ||
             ( strcasecmp ( key, "NAME" ) == 0 ) ||
             ( strcasecmp ( key, "PATH" ) == 0 ) ) {
                /* Nothing to do */
                return 0;
        }

        /* Do nothing more unless we have a settings block */
        if ( ! settings ) {
                rc = -ENOTSUP;
                goto err_no_settings;
        }

        /* Identify setting */
        setting = find_setting ( key );
        if ( ! setting ) {
                DBGC ( snpdev, "SNPDEV %p no such setting \"%s\"\n",
                       snpdev, key );
                rc = -ENODEV;
                goto err_find_setting;
        }

        /* Allocate buffer */
        len = ( strlen ( value ) / 4 );
        buf = zalloc ( len + 1 /* NUL */ );
        if ( ! buf ) {
                rc = -ENOMEM;
                goto err_alloc;
        }

        /* Decode value */
        tmp[4] = '\0';
        for ( i = 0 ; i < len ; i++ ) {
                memcpy ( tmp, ( value + ( i * 4 ) ), 4 );
                buf[i] = strtoul ( tmp, &endp, 16 );
                if ( endp != &tmp[4] ) {
                        DBGC ( snpdev, "SNPDEV %p invalid character %s\n",
                               snpdev, tmp );
                        rc = -EINVAL;
                        goto err_inval;
                }
        }

        /* Store value */
        if ( ( rc = storef_setting ( settings, setting, buf ) ) != 0 ) {
                DBGC ( snpdev, "SNPDEV %p could not store \"%s\" into %s: %s\n",
                       snpdev, buf, setting->name, strerror ( rc ) );
                goto err_storef;
        }

        /* Success */
        rc = 0;

 err_storef:
 err_inval:
        free ( buf );
 err_alloc:
 err_find_setting:
 err_no_settings:
        return rc;
}
static int efi_snp_hii_process ( struct efi_snp_device snpdev,
wchar_t string,
wchar_t **  progress,
wchar_t **  results,
int *  have_setting,
int(*)(struct efi_snp_device *, const char *key, const char *value, wchar_t **results, int *have_setting)  process 
) [static]

Process portion of HII configuration string.

Parameters:
snpdevSNP device
stringHII configuration string
progressProgress through HII configuration string
resultsResults string
have_settingFlag indicating detection of a setting (unused)
processFunction used to process key=value pairs
Return values:
rcReturn status code

Definition at line 468 of file efi_snp_hii.c.

References ENOMEM, free, key, NULL, rc, string, value, and zalloc().

Referenced by efi_snp_hii_extract_config(), and efi_snp_hii_route_config().

                                                                           {
        wchar_t *wkey = string;
        wchar_t *wend = string;
        wchar_t *wvalue = NULL;
        size_t key_len;
        size_t value_len;
        void *temp;
        char *key;
        char *value;
        int rc;

        /* Locate key, value (if any), and end */
        while ( *wend ) {
                if ( *wend == L'&' )
                        break;
                if ( *(wend++) == L'=' )
                        wvalue = wend;
        }

        /* Allocate memory for key and value */
        key_len = ( ( wvalue ? ( wvalue - 1 ) : wend ) - wkey );
        value_len = ( wvalue ? ( wend - wvalue ) : 0 );
        temp = zalloc ( key_len + 1 /* NUL */ + value_len + 1 /* NUL */ );
        if ( ! temp )
                return -ENOMEM;
        key = temp;
        value = ( temp + key_len + 1 /* NUL */ );

        /* Copy key and value */
        while ( key_len-- )
                key[key_len] = wkey[key_len];
        while ( value_len-- )
                value[value_len] = wvalue[value_len];

        /* Process key and value */
        if ( ( rc = process ( snpdev, key, value, results,
                              have_setting ) ) != 0 ) {
                goto err;
        }

        /* Update progress marker */
        *progress = wend;

 err:
        /* Free temporary storage */
        free ( temp );

        return rc;
}
static EFI_STATUS EFIAPI efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL hii,
EFI_STRING  request,
EFI_STRING progress,
EFI_STRING results 
) [static]

Fetch configuration.

Parameters:
hiiHII configuration access protocol
requestConfiguration to fetch
Return values:
progressProgress made through configuration to fetch
resultsQuery results
efircEFI status code

Definition at line 535 of file efi_snp_hii.c.

References container_of, DBGC, EFI_INVALID_PARAMETER, efi_snp_hii_fetch(), efi_snp_hii_process(), efi_snp_hii_setting_applies(), EFIRC, for_each_table_entry, setting::name, NULL, rc, and SETTINGS.

                                                   {
        struct efi_snp_device *snpdev =
                container_of ( hii, struct efi_snp_device, hii );
        int have_setting = 0;
        wchar_t *pos;
        int rc;

        DBGC ( snpdev, "SNPDEV %p ExtractConfig request \"%ls\"\n",
               snpdev, request );

        /* Initialise results */
        *results = NULL;

        /* Work around apparently broken UEFI specification */
        if ( ! ( request && request[0] ) ) {
                DBGC ( snpdev, "SNPDEV %p ExtractConfig ignoring malformed "
                       "request\n", snpdev );
                return EFI_INVALID_PARAMETER;
        }

        /* Process all request fragments */
        for ( pos = *progress = request ; *progress && **progress ;
              pos = *progress + 1 ) {
                if ( ( rc = efi_snp_hii_process ( snpdev, pos, progress,
                                                  results, &have_setting,
                                                  efi_snp_hii_fetch ) ) != 0 ) {
                        return EFIRC ( rc );
                }
        }

        /* If we have no explicit request, return all settings */
        if ( ! have_setting ) {
                struct setting *setting;

                for_each_table_entry ( setting, SETTINGS ) {
                        if ( ! efi_snp_hii_setting_applies ( snpdev, setting ) )
                                continue;
                        if ( ( rc = efi_snp_hii_fetch ( snpdev, setting->name,
                                                        NULL, results,
                                                        NULL ) ) != 0 ) {
                                return EFIRC ( rc );
                        }
                }
        }

        DBGC ( snpdev, "SNPDEV %p ExtractConfig results \"%ls\"\n",
               snpdev, *results );
        return 0;
}
static EFI_STATUS EFIAPI efi_snp_hii_route_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL hii,
EFI_STRING  config,
EFI_STRING progress 
) [static]

Store configuration.

Parameters:
hiiHII configuration access protocol
configConfiguration to store
Return values:
progressProgress made through configuration to store
efircEFI status code

Definition at line 596 of file efi_snp_hii.c.

References container_of, DBGC, efi_snp_hii_process(), efi_snp_hii_store(), EFIRC, NULL, and rc.

                                                                     {
        struct efi_snp_device *snpdev =
                container_of ( hii, struct efi_snp_device, hii );
        wchar_t *pos;
        int rc;

        DBGC ( snpdev, "SNPDEV %p RouteConfig \"%ls\"\n", snpdev, config );

        /* Process all request fragments */
        for ( pos = *progress = config ; *progress && **progress ;
              pos = *progress + 1 ) {
                if ( ( rc = efi_snp_hii_process ( snpdev, pos, progress,
                                                  NULL, NULL,
                                                  efi_snp_hii_store ) ) != 0 ) {
                        return EFIRC ( rc );
                }
        }

        return 0;
}
static EFI_STATUS EFIAPI efi_snp_hii_callback ( const EFI_HII_CONFIG_ACCESS_PROTOCOL hii,
EFI_BROWSER_ACTION action  __unused,
EFI_QUESTION_ID question_id  __unused,
UINT8 type  __unused,
EFI_IFR_TYPE_VALUE *value  __unused,
EFI_BROWSER_ACTION_REQUEST *action_request  __unused 
) [static]

Handle form actions.

Parameters:
hiiHII configuration access protocol
actionForm browser action
question_idQuestion ID
typeType of value
valueValue
Return values:
action_requestAction requested by driver
efircEFI status code

Definition at line 630 of file efi_snp_hii.c.

References container_of, DBGC, and EFI_UNSUPPORTED.

                                                                             {
        struct efi_snp_device *snpdev =
                container_of ( hii, struct efi_snp_device, hii );

        DBGC ( snpdev, "SNPDEV %p Callback\n", snpdev );
        return EFI_UNSUPPORTED;
}
int efi_snp_hii_install ( struct efi_snp_device snpdev)

Install HII protocol and packages for SNP device.

Parameters:
snpdevSNP device
Return values:
rcReturn status code

Definition at line 655 of file efi_snp_hii.c.

References EFI_SYSTEM_TABLE::BootServices, DBGC, EEFI, efi_child_add(), efi_child_del(), efi_device_path_protocol_guid, efi_devpath_len(), efi_hii_config_access_protocol_guid, efi_snp_hii_package_list(), efi_snp_hii_random_guid(), efi_systab, END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, ENOMEM, ENOTSUP, free, VENDOR_DEVICE_PATH::Guid, efi_snp_device::handle, HARDWARE_DEVICE_PATH, VENDOR_DEVICE_PATH::Header, efi_snp_device::hii, efi_snp_device::hii_child_handle, efi_snp_device::hii_child_path, efi_snp_device::hii_handle, HW_VENDOR_DP, EFI_BOOT_SERVICES::InstallMultipleProtocolInterfaces, EFI_DEVICE_PATH_PROTOCOL::Length, memcpy(), _EFI_HII_DATABASE_PROTOCOL::NewPackageList, NULL, efi_snp_device::package_list, efi_snp_device::path, rc, _EFI_HII_DATABASE_PROTOCOL::RemovePackageList, strerror(), EFI_DEVICE_PATH_PROTOCOL::SubType, EFI_DEVICE_PATH_PROTOCOL::Type, EFI_BOOT_SERVICES::UninstallMultipleProtocolInterfaces, and zalloc().

Referenced by efi_snp_probe().

                                                          {
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
        VENDOR_DEVICE_PATH *vendor_path;
        EFI_DEVICE_PATH_PROTOCOL *path_end;
        size_t path_prefix_len;
        int efirc;
        int rc;

        /* Do nothing if HII database protocol is not supported */
        if ( ! efihii ) {
                rc = -ENOTSUP;
                goto err_no_hii;
        }

        /* Initialise HII protocol */
        memcpy ( &snpdev->hii, &efi_snp_device_hii, sizeof ( snpdev->hii ) );

        /* Create HII package list */
        snpdev->package_list = efi_snp_hii_package_list ( snpdev );
        if ( ! snpdev->package_list ) {
                DBGC ( snpdev, "SNPDEV %p could not create HII package list\n",
                       snpdev );
                rc = -ENOMEM;
                goto err_build_package_list;
        }

        /* Allocate the new device path */
        path_prefix_len = efi_devpath_len ( snpdev->path );
        snpdev->hii_child_path = zalloc ( path_prefix_len +
                                          sizeof ( *vendor_path ) +
                                          sizeof ( *path_end ) );
        if ( ! snpdev->hii_child_path ) {
                DBGC ( snpdev,
                       "SNPDEV %p could not allocate HII child device path\n",
                       snpdev );
                rc = -ENOMEM;
                goto err_alloc_child_path;
        }

        /* Populate the device path */
        memcpy ( snpdev->hii_child_path, snpdev->path, path_prefix_len );
        vendor_path = ( ( ( void * ) snpdev->hii_child_path ) +
                        path_prefix_len );
        vendor_path->Header.Type = HARDWARE_DEVICE_PATH;
        vendor_path->Header.SubType = HW_VENDOR_DP;
        vendor_path->Header.Length[0] = sizeof ( *vendor_path );
        efi_snp_hii_random_guid ( &vendor_path->Guid );
        path_end = ( ( void * ) ( vendor_path + 1 ) );
        path_end->Type = END_DEVICE_PATH_TYPE;
        path_end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
        path_end->Length[0] = sizeof ( *path_end );

        /* Create device path and child handle for HII association */
        if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
                        &snpdev->hii_child_handle,
                        &efi_device_path_protocol_guid, snpdev->hii_child_path,
                        NULL ) ) != 0 ) {
                rc = -EEFI ( efirc );
                DBGC ( snpdev, "SNPDEV %p could not create HII child handle: "
                       "%s\n", snpdev, strerror ( rc ) );
                goto err_hii_child_handle;
        }

        /* Add HII packages */
        if ( ( efirc = efihii->NewPackageList ( efihii, snpdev->package_list,
                                                snpdev->hii_child_handle,
                                                &snpdev->hii_handle ) ) != 0 ) {
                rc = -EEFI ( efirc );
                DBGC ( snpdev, "SNPDEV %p could not add HII packages: %s\n",
                       snpdev, strerror ( rc ) );
                goto err_new_package_list;
        }

        /* Install HII protocol */
        if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
                         &snpdev->hii_child_handle,
                         &efi_hii_config_access_protocol_guid, &snpdev->hii,
                         NULL ) ) != 0 ) {
                rc = -EEFI ( efirc );
                DBGC ( snpdev, "SNPDEV %p could not install HII protocol: %s\n",
                       snpdev, strerror ( rc ) );
                goto err_install_protocol;
        }

        /* Add as child of handle with SNP instance */
        if ( ( rc = efi_child_add ( snpdev->handle,
                                    snpdev->hii_child_handle ) ) != 0 ) {
                DBGC ( snpdev,
                       "SNPDEV %p could not adopt HII child handle: %s\n",
                       snpdev, strerror ( rc ) );
                goto err_efi_child_add;
        }

        return 0;

        efi_child_del ( snpdev->handle, snpdev->hii_child_handle );
 err_efi_child_add:
        bs->UninstallMultipleProtocolInterfaces (
                        snpdev->hii_child_handle,
                        &efi_hii_config_access_protocol_guid, &snpdev->hii,
                        NULL );
 err_install_protocol:
        efihii->RemovePackageList ( efihii, snpdev->hii_handle );
 err_new_package_list:
        bs->UninstallMultipleProtocolInterfaces (
                        snpdev->hii_child_handle,
                        &efi_device_path_protocol_guid, snpdev->hii_child_path,
                        NULL );
 err_hii_child_handle:
        free ( snpdev->hii_child_path );
        snpdev->hii_child_path = NULL;
 err_alloc_child_path:
        free ( snpdev->package_list );
        snpdev->package_list = NULL;
 err_build_package_list:
 err_no_hii:
        return rc;
}
void efi_snp_hii_uninstall ( struct efi_snp_device snpdev)

Variable Documentation

EFI platform setup formset GUID.

Definition at line 71 of file efi_snp_hii.c.

Referenced by efi_snp_hii_package_list().

EFI IBM UCM compliant formset GUID.

Definition at line 75 of file efi_snp_hii.c.

Referenced by efi_snp_hii_package_list().

EFI HII database protocol.

Definition at line 78 of file efi_snp_hii.c.

Initial value:
 {
        .ExtractConfig  = efi_snp_hii_extract_config,
        .RouteConfig    = efi_snp_hii_route_config,
        .Callback       = efi_snp_hii_callback,
}

HII configuration access protocol.

Definition at line 643 of file efi_snp_hii.c.