[efi] Add support for HII

Some EFI platforms expect us to provide an HII interface to display
information about the driver.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/5/head
Michael Brown 2011-04-07 23:03:05 +01:00
parent af5e74990c
commit 1c67e20261
7 changed files with 1690 additions and 0 deletions

View File

@ -0,0 +1,37 @@
/** @file
GUID indicates that the form set contains forms designed to be used
for platform configuration and this form set will be displayed.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
@par Revision Reference:
GUID defined in UEFI 2.1.
**/
#ifndef __HII_PLATFORM_SETUP_FORMSET_GUID_H__
#define __HII_PLATFORM_SETUP_FORMSET_GUID_H__
FILE_LICENCE ( BSD3 );
#define EFI_HII_PLATFORM_SETUP_FORMSET_GUID \
{ 0x93039971, 0x8545, 0x4b04, { 0xb4, 0x5e, 0x32, 0xeb, 0x83, 0x26, 0x4, 0xe } }
#define EFI_HII_DRIVER_HEALTH_FORMSET_GUID \
{ 0xf22fc20c, 0x8cf4, 0x45eb, { 0x8e, 0x6, 0xad, 0x4e, 0x50, 0xb9, 0x5d, 0xd3 } }
#define EFI_HII_USER_CREDENTIAL_FORMSET_GUID \
{ 0x337f4407, 0x5aee, 0x4b83, { 0xb2, 0xa7, 0x4e, 0xad, 0xca, 0x30, 0x88, 0xcd } }
extern EFI_GUID gEfiHiiPlatformSetupFormsetGuid;
extern EFI_GUID gEfiHiiDriverHealthFormsetGuid;
extern EFI_GUID gEfiHiiUserCredentialFormsetGuid;
#endif

View File

@ -0,0 +1,222 @@
/** @file
EDKII extented HII IFR guid opcodes.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __MDEMODULE_HII_H__
#define __MDEMODULE_HII_H__
FILE_LICENCE ( BSD3 );
#define NARROW_CHAR 0xFFF0
#define WIDE_CHAR 0xFFF1
#define NON_BREAKING_CHAR 0xFFF2
///
/// State defined for password statemachine .
///
#define BROWSER_STATE_VALIDATE_PASSWORD 0
#define BROWSER_STATE_SET_PASSWORD 1
///
/// GUIDed opcodes defined for EDKII implementation.
///
#define EFI_IFR_TIANO_GUID \
{ 0xf0b1735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38, 0xaf, 0x48, 0xce} }
#pragma pack(1)
///
/// EDKII implementation extension opcodes, new extension can be added here later.
///
#define EFI_IFR_EXTEND_OP_LABEL 0x0
#define EFI_IFR_EXTEND_OP_BANNER 0x1
#define EFI_IFR_EXTEND_OP_TIMEOUT 0x2
#define EFI_IFR_EXTEND_OP_CLASS 0x3
#define EFI_IFR_EXTEND_OP_SUBCLASS 0x4
///
/// Label opcode.
///
typedef struct _EFI_IFR_GUID_LABEL {
EFI_IFR_OP_HEADER Header;
///
/// EFI_IFR_TIANO_GUID.
///
EFI_GUID Guid;
///
/// EFI_IFR_EXTEND_OP_LABEL.
///
UINT8 ExtendOpCode;
///
/// Label Number.
///
UINT16 Number;
} EFI_IFR_GUID_LABEL;
#define EFI_IFR_BANNER_ALIGN_LEFT 0
#define EFI_IFR_BANNER_ALIGN_CENTER 1
#define EFI_IFR_BANNER_ALIGN_RIGHT 2
///
/// Banner opcode.
///
typedef struct _EFI_IFR_GUID_BANNER {
EFI_IFR_OP_HEADER Header;
///
/// EFI_IFR_TIANO_GUID.
///
EFI_GUID Guid;
///
/// EFI_IFR_EXTEND_OP_BANNER
///
UINT8 ExtendOpCode;
EFI_STRING_ID Title; ///< The string token for the banner title.
UINT16 LineNumber; ///< 1-based line number.
UINT8 Alignment; ///< left, center, or right-aligned.
} EFI_IFR_GUID_BANNER;
///
/// Timeout opcode.
///
typedef struct _EFI_IFR_GUID_TIMEOUT {
EFI_IFR_OP_HEADER Header;
///
/// EFI_IFR_TIANO_GUID.
///
EFI_GUID Guid;
///
/// EFI_IFR_EXTEND_OP_TIMEOUT.
///
UINT8 ExtendOpCode;
UINT16 TimeOut; ///< TimeOut Value.
} EFI_IFR_GUID_TIMEOUT;
#define EFI_NON_DEVICE_CLASS 0x00
#define EFI_DISK_DEVICE_CLASS 0x01
#define EFI_VIDEO_DEVICE_CLASS 0x02
#define EFI_NETWORK_DEVICE_CLASS 0x04
#define EFI_INPUT_DEVICE_CLASS 0x08
#define EFI_ON_BOARD_DEVICE_CLASS 0x10
#define EFI_OTHER_DEVICE_CLASS 0x20
///
/// Device Class opcode.
///
typedef struct _EFI_IFR_GUID_CLASS {
EFI_IFR_OP_HEADER Header;
///
/// EFI_IFR_TIANO_GUID.
///
EFI_GUID Guid;
///
/// EFI_IFR_EXTEND_OP_CLASS.
///
UINT8 ExtendOpCode;
UINT16 Class; ///< Device Class from the above.
} EFI_IFR_GUID_CLASS;
#define EFI_SETUP_APPLICATION_SUBCLASS 0x00
#define EFI_GENERAL_APPLICATION_SUBCLASS 0x01
#define EFI_FRONT_PAGE_SUBCLASS 0x02
#define EFI_SINGLE_USE_SUBCLASS 0x03
///
/// SubClass opcode
///
typedef struct _EFI_IFR_GUID_SUBCLASS {
EFI_IFR_OP_HEADER Header;
///
/// EFI_IFR_TIANO_GUID.
///
EFI_GUID Guid;
///
/// EFI_IFR_EXTEND_OP_SUBCLASS.
///
UINT8 ExtendOpCode;
UINT16 SubClass; ///< Sub Class type from the above.
} EFI_IFR_GUID_SUBCLASS;
///
/// GUIDed opcodes support for framework vfr.
///
#define EFI_IFR_FRAMEWORK_GUID \
{ 0x31ca5d1a, 0xd511, 0x4931, { 0xb7, 0x82, 0xae, 0x6b, 0x2b, 0x17, 0x8c, 0xd7 } }
///
/// Two extended opcodes are added, and new extensions can be added here later.
/// One is for framework OneOf question Option Key value;
/// another is for framework vareqval.
///
#define EFI_IFR_EXTEND_OP_OPTIONKEY 0x0
#define EFI_IFR_EXTEND_OP_VAREQNAME 0x1
///
/// Store the framework vfr option key value.
///
typedef struct _EFI_IFR_GUID_OPTIONKEY {
EFI_IFR_OP_HEADER Header;
///
/// EFI_IFR_FRAMEWORK_GUID.
///
EFI_GUID Guid;
///
/// EFI_IFR_EXTEND_OP_OPTIONKEY.
///
UINT8 ExtendOpCode;
///
/// OneOf Questiond ID binded by OneOf Option.
///
EFI_QUESTION_ID QuestionId;
///
/// The OneOf Option Value.
///
EFI_IFR_TYPE_VALUE OptionValue;
///
/// The Framework OneOf Option Key Value.
///
UINT16 KeyValue;
} EFI_IFR_GUID_OPTIONKEY;
///
/// Store the framework vfr vareqval name number.
///
typedef struct _EFI_IFR_GUID_VAREQNAME {
EFI_IFR_OP_HEADER Header;
///
/// EFI_IFR_FRAMEWORK_GUID.
///
EFI_GUID Guid;
///
/// EFI_IFR_EXTEND_OP_VAREQNAME.
///
UINT8 ExtendOpCode;
///
/// Question ID of the Numeric Opcode created.
///
EFI_QUESTION_ID QuestionId;
///
/// For vareqval (0x100), NameId is 0x100.
/// This value will convert to a Unicode String following this rule;
/// sprintf(StringBuffer, "%d", NameId) .
/// The the Unicode String will be used as a EFI Variable Name.
///
UINT16 NameId;
} EFI_IFR_GUID_VAREQNAME;
#pragma pack()
extern EFI_GUID gEfiIfrTianoGuid;
extern EFI_GUID gEfiIfrFrameworkGuid;
#endif

View File

@ -0,0 +1,177 @@
/** @file
This protocol is defined in UEFI spec.
The EFI_FORM_BROWSER2_PROTOCOL is the interface to call for drivers to
leverage the EFI configuration driver interface.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_FORM_BROWSER2_H__
#define __EFI_FORM_BROWSER2_H__
FILE_LICENCE ( BSD3 );
#include <ipxe/efi/Guid/HiiPlatformSetupFormset.h>
#define EFI_FORM_BROWSER2_PROTOCOL_GUID \
{0xb9d4c360, 0xbcfb, 0x4f9b, {0x92, 0x98, 0x53, 0xc1, 0x36, 0x98, 0x22, 0x58 }}
typedef struct _EFI_FORM_BROWSER2_PROTOCOL EFI_FORM_BROWSER2_PROTOCOL;
/**
@param LeftColumn The value that designates the text column
where the browser window will begin from
the left-hand side of the screen
@param RightColumn The value that designates the text
column where the browser window will end
on the right-hand side of the screen.
@param TopRow The value that designates the text row from the
top of the screen where the browser window
will start.
@param BottomRow The value that designates the text row from the
bottom of the screen where the browser
window will end.
**/
typedef struct {
UINTN LeftColumn;
UINTN RightColumn;
UINTN TopRow;
UINTN BottomRow;
} EFI_SCREEN_DESCRIPTOR;
typedef UINTN EFI_BROWSER_ACTION_REQUEST;
#define EFI_BROWSER_ACTION_REQUEST_NONE 0
#define EFI_BROWSER_ACTION_REQUEST_RESET 1
#define EFI_BROWSER_ACTION_REQUEST_SUBMIT 2
#define EFI_BROWSER_ACTION_REQUEST_EXIT 3
/**
Initialize the browser to display the specified configuration forms.
This function is the primary interface to the internal forms-based browser.
The forms browser will display forms associated with the specified Handles.
The browser will select all forms in packages which have the specified Type
and (for EFI_HII_PACKAGE_TYPE_GUID) the specified PackageGuid.
@param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL instance
@param Handles A pointer to an array of Handles. This value should correspond
to the value of the HII form package that is required to be displayed.
@param HandleCount The number of Handles specified in Handle.
@param FormSetGuid This field points to the EFI_GUID which must match the Guid field or one of the
elements of the ClassId field in the EFI_IFR_FORM_SET op-code. If
FormsetGuid is NULL, then this function will display the the form set class
EFI_HII_PLATFORM_SETUP_FORMSET_GUID.
@param FormId This field specifies the identifier of the form within the form set to render as the first
displayable page. If this field has a value of 0x0000, then the Forms Browser will
render the first enabled form in the form set.
@param ScreenDimensions Points to recommended form dimensions, including any non-content area, in
characters.
@param ActionRequest Points to the action recommended by the form.
@retval EFI_SUCCESS The function completed successfully
@retval EFI_NOT_FOUND The variable was not found.
@retval EFI_INVALID_PARAMETER One of the parameters has an
invalid value.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_SEND_FORM2)(
IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
IN EFI_HII_HANDLE *Handle,
IN UINTN HandleCount,
IN EFI_GUID *FormSetGuid, OPTIONAL
IN EFI_FORM_ID FormId, OPTIONAL
IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL
);
/**
This function is called by a callback handler to retrieve uncommitted state data from the browser.
This routine is called by a routine which was called by the
browser. This routine called this service in the browser to
retrieve or set certain uncommitted state information.
@param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL instance.
@param ResultsDataSize A pointer to the size of the buffer
associated with ResultsData. On input, the size in
bytes of ResultsData. On output, the size of data
returned in ResultsData.
@param ResultsData A string returned from an IFR browser or
equivalent. The results string will have
no routing information in them.
@param RetrieveData A BOOLEAN field which allows an agent to
retrieve (if RetrieveData = TRUE) data
from the uncommitted browser state
information or set (if RetrieveData =
FALSE) data in the uncommitted browser
state information.
@param VariableGuid An optional field to indicate the target
variable GUID name to use.
@param VariableName An optional field to indicate the target
human-readable variable name.
@retval EFI_SUCCESS The results have been distributed or are
awaiting distribution.
@retval EFI_OUT_OF_RESOURCES The ResultsDataSize specified
was too small to contain the
results data.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_BROWSER_CALLBACK2)(
IN CONST EFI_FORM_BROWSER2_PROTOCOL *This,
IN OUT UINTN *ResultsDataSize,
IN OUT EFI_STRING ResultsData,
IN CONST BOOLEAN RetrieveData,
IN CONST EFI_GUID *VariableGuid, OPTIONAL
IN CONST CHAR16 *VariableName OPTIONAL
);
///
/// This interface will allow the caller to direct the configuration
/// driver to use either the HII database or use the passed-in packet of data.
///
struct _EFI_FORM_BROWSER2_PROTOCOL {
EFI_SEND_FORM2 SendForm;
EFI_BROWSER_CALLBACK2 BrowserCallback;
} ;
extern EFI_GUID gEfiFormBrowser2ProtocolGuid;
#endif

View File

@ -0,0 +1,221 @@
/** @file
The EFI HII results processing protocol invokes this type of protocol
when it needs to forward results to a driver's configuration handler.
This protocol is published by drivers providing and requesting
configuration data from HII. It may only be invoked by HII.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_HII_CONFIG_ACCESS_H__
#define __EFI_HII_CONFIG_ACCESS_H__
FILE_LICENCE ( BSD3 );
#include <ipxe/efi/Protocol/FormBrowser2.h>
#define EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID \
{ 0x330d4706, 0xf2a0, 0x4e4f, { 0xa3, 0x69, 0xb6, 0x6f, 0xa8, 0xd5, 0x43, 0x85 } }
typedef struct _EFI_HII_CONFIG_ACCESS_PROTOCOL EFI_HII_CONFIG_ACCESS_PROTOCOL;
typedef UINTN EFI_BROWSER_ACTION;
#define EFI_BROWSER_ACTION_CHANGING 0
#define EFI_BROWSER_ACTION_CHANGED 1
#define EFI_BROWSER_ACTION_RETRIEVE 2
#define EFI_BROWSER_ACTION_FORM_OPEN 3
#define EFI_BROWSER_ACTION_FORM_CLOSE 4
/**
This function allows the caller to request the current
configuration for one or more named elements. The resulting
string is in <ConfigAltResp> format. Any and all alternative
configuration strings shall also be appended to the end of the
current configuration string. If they are, they must appear
after the current configuration. They must contain the same
routing (GUID, NAME, PATH) as the current configuration string.
They must have an additional description indicating the type of
alternative configuration the string represents,
"ALTCFG=<StringToken>". That <StringToken> (when
converted from Hex UNICODE to binary) is a reference to a
string in the associated string pack.
@param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
@param Request A null-terminated Unicode string in
<ConfigRequest> format. Note that this
includes the routing information as well as
the configurable name / value pairs. It is
invalid for this string to be in
<MultiConfigRequest> format.
If a NULL is passed in for the Request field,
all of the settings being abstracted by this function
will be returned in the Results field. In addition,
if a ConfigHdr is passed in with no request elements,
all of the settings being abstracted for that particular
ConfigHdr reference will be returned in the Results Field.
@param Progress On return, points to a character in the
Request string. Points to the string's null
terminator if request was successful. Points
to the most recent "&" before the first
failing name / value pair (or the beginning
of the string if the failure is in the first
name / value pair) if the request was not
successful.
@param Results A null-terminated Unicode string in
<MultiConfigAltResp> format which has all values
filled in for the names in the Request string.
String to be allocated by the called function.
@retval EFI_SUCCESS The Results string is filled with the
values corresponding to all requested
names.
@retval EFI_OUT_OF_RESOURCES Not enough memory to store the
parts of the results that must be
stored awaiting possible future
protocols.
@retval EFI_NOT_FOUND Routing data doesn't match any
known driver. Progress set to the
first character in the routing header.
Note: There is no requirement that the
driver validate the routing data. It
must skip the <ConfigHdr> in order to
process the names.
@retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
to most recent "&" before the
error or the beginning of the
string.
@retval EFI_INVALID_PARAMETER Unknown name. Progress points
to the & before the name in
question.
**/
typedef
EFI_STATUS
(EFIAPI * EFI_HII_ACCESS_EXTRACT_CONFIG)(
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
IN CONST EFI_STRING Request,
OUT EFI_STRING *Progress,
OUT EFI_STRING *Results
);
/**
This function applies changes in a driver's configuration.
Input is a Configuration, which has the routing data for this
driver followed by name / value configuration pairs. The driver
must apply those pairs to its configurable storage. If the
driver's configuration is stored in a linear block of data
and the driver's name / value pairs are in <BlockConfig>
format, it may use the ConfigToBlock helper function (above) to
simplify the job.
@param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
@param Configuration A null-terminated Unicode string in
<ConfigString> format.
@param Progress A pointer to a string filled in with the
offset of the most recent '&' before the
first failing name / value pair (or the
beginn ing of the string if the failure
is in the first name / value pair) or
the terminating NULL if all was
successful.
@retval EFI_SUCCESS The results have been distributed or are
awaiting distribution.
@retval EFI_OUT_OF_RESOURCES Not enough memory to store the
parts of the results that must be
stored awaiting possible future
protocols.
@retval EFI_INVALID_PARAMETERS Passing in a NULL for the
Results parameter would result
in this type of error.
@retval EFI_NOT_FOUND Target for the specified routing data
was not found
**/
typedef
EFI_STATUS
(EFIAPI * EFI_HII_ACCESS_ROUTE_CONFIG)(
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
IN CONST EFI_STRING Configuration,
OUT EFI_STRING *Progress
);
/**
This function is called to provide results data to the driver.
This data consists of a unique key that is used to identify
which data is either being passed back or being asked for.
@param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
@param Action Specifies the type of action taken by the browser.
@param QuestionId A unique value which is sent to the original
exporting driver so that it can identify the type
of data to expect. The format of the data tends to
vary based on the opcode that generated the callback.
@param Type The type of value for the question.
@param Value A pointer to the data being sent to the original
exporting driver.
@param ActionRequest On return, points to the action requested by the
callback function.
@retval EFI_SUCCESS The callback successfully handled the action.
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
variable and its data.
@retval EFI_DEVICE_ERROR The variable could not be saved.
@retval EFI_UNSUPPORTED The specified Action is not supported by the
callback.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_HII_ACCESS_FORM_CALLBACK)(
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
IN EFI_BROWSER_ACTION Action,
IN EFI_QUESTION_ID QuestionId,
IN UINT8 Type,
IN OUT EFI_IFR_TYPE_VALUE *Value,
OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
)
;
///
/// This protocol provides a callable interface between the HII and
/// drivers. Only drivers which provide IFR data to HII are required
/// to publish this protocol.
///
struct _EFI_HII_CONFIG_ACCESS_PROTOCOL {
EFI_HII_ACCESS_EXTRACT_CONFIG ExtractConfig;
EFI_HII_ACCESS_ROUTE_CONFIG RouteConfig;
EFI_HII_ACCESS_FORM_CALLBACK Callback;
} ;
extern EFI_GUID gEfiHiiConfigAccessProtocolGuid;
#endif

View File

@ -0,0 +1,519 @@
/** @file
The file provides Database manager for HII-related data
structures.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __HII_DATABASE_H__
#define __HII_DATABASE_H__
FILE_LICENCE ( BSD3 );
#define EFI_HII_DATABASE_PROTOCOL_GUID \
{ 0xef9fc172, 0xa1b2, 0x4693, { 0xb3, 0x27, 0x6d, 0x32, 0xfc, 0x41, 0x60, 0x42 } }
typedef struct _EFI_HII_DATABASE_PROTOCOL EFI_HII_DATABASE_PROTOCOL;
///
/// EFI_HII_DATABASE_NOTIFY_TYPE.
///
typedef UINTN EFI_HII_DATABASE_NOTIFY_TYPE;
#define EFI_HII_DATABASE_NOTIFY_NEW_PACK 0x00000001
#define EFI_HII_DATABASE_NOTIFY_REMOVE_PACK 0x00000002
#define EFI_HII_DATABASE_NOTIFY_EXPORT_PACK 0x00000004
#define EFI_HII_DATABASE_NOTIFY_ADD_PACK 0x00000008
/**
Functions which are registered to receive notification of
database events have this prototype. The actual event is encoded
in NotifyType. The following table describes how PackageType,
PackageGuid, Handle, and Package are used for each of the
notification types.
@param PackageType Package type of the notification.
@param PackageGuid If PackageType is
EFI_HII_PACKAGE_TYPE_GUID, then this is
the pointer to the GUID from the Guid
field of EFI_HII_PACKAGE_GUID_HEADER.
Otherwise, it must be NULL.
@param Package Points to the package referred to by the notification.
@param Handle The handle of the package
list which contains the specified package.
@param NotifyType The type of change concerning the
database. See
EFI_HII_DATABASE_NOTIFY_TYPE.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_HII_DATABASE_NOTIFY)(
IN UINT8 PackageType,
IN CONST EFI_GUID *PackageGuid,
IN CONST EFI_HII_PACKAGE_HEADER *Package,
IN EFI_HII_HANDLE Handle,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
);
/**
This function adds the packages in the package list to the
database and returns a handle. If there is a
EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then
this function will create a package of type
EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list. For
each package in the package list, registered functions with the
notification type NEW_PACK and having the same package type will
be called. For each call to NewPackageList(), there should be a
corresponding call to
EFI_HII_DATABASE_PROTOCOL.RemovePackageList().
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER structure.
@param DriverHandle Associate the package list with this EFI handle.
If a NULL is specified, this data will not be associate
with any drivers and cannot have a callback induced.
@param Handle A pointer to the EFI_HII_HANDLE instance.
@retval EFI_SUCCESS The package list associated with the
Handle was added to the HII database.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary
resources for the new database
contents.
@retval EFI_INVALID_PARAMETER PackageList is NULL, or Handle is NULL.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_HII_DATABASE_NEW_PACK)(
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
IN EFI_HANDLE DriverHandle, OPTIONAL
OUT EFI_HII_HANDLE *Handle
);
/**
This function removes the package list that is associated with a
handle Handle from the HII database. Before removing the
package, any registered functions with the notification type
REMOVE_PACK and the same package type will be called. For each
call to EFI_HII_DATABASE_PROTOCOL.NewPackageList(), there should
be a corresponding call to RemovePackageList.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param Handle The handle that was registered to the data
that is requested for removal.
@retval EFI_SUCCESS The data associated with the Handle was
removed from the HII database.
@retval EFI_NOT_FOUND The specified Handle is not in database.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_HII_DATABASE_REMOVE_PACK)(
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN EFI_HII_HANDLE Handle
);
/**
This function updates the existing package list (which has the
specified Handle) in the HII databases, using the new package
list specified by PackageList. The update process has the
following steps: Collect all the package types in the package
list specified by PackageList. A package type consists of the
Type field of EFI_HII_PACKAGE_HEADER and, if the Type is
EFI_HII_PACKAGE_TYPE_GUID, the Guid field, as defined in
EFI_HII_PACKAGE_GUID_HEADER. Iterate through the packages within
the existing package list in the HII database specified by
Handle. If a package's type matches one of the collected types collected
in step 1, then perform the following steps:
- Call any functions registered with the notification type
REMOVE_PACK.
- Remove the package from the package list and the HII
database.
Add all of the packages within the new package list specified
by PackageList, using the following steps:
- Add the package to the package list and the HII database.
- Call any functions registered with the notification type
ADD_PACK.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param Handle The handle that was registered to the data
that is requested for removal.
@param PackageList A pointer to an EFI_HII_PACKAGE_LIST
package.
@retval EFI_SUCCESS The HII database was successfully updated.
@retval EFI_OUT_OF_RESOURCES Unable to allocate enough memory
for the updated database.
@retval EFI_INVALID_PARAMETER PackageList was NULL.
@retval EFI_NOT_FOUND The specified Handle is not in database.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_HII_DATABASE_UPDATE_PACK)(
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN EFI_HII_HANDLE Handle,
IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList
);
/**
This function returns a list of the package handles of the
specified type that are currently active in the database. The
pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package
handles to be listed.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param PackageType Specifies the package type of the packages
to list or EFI_HII_PACKAGE_TYPE_ALL for
all packages to be listed.
@param PackageGuid If PackageType is
EFI_HII_PACKAGE_TYPE_GUID, then this is
the pointer to the GUID which must match
the Guid field of
EFI_HII_PACKAGE_GUID_HEADER. Otherwise, it
must be NULL.
@param HandleBufferLength On input, a pointer to the length
of the handle buffer. On output,
the length of the handle buffer
that is required for the handles found.
@param Handle An array of EFI_HII_HANDLE instances returned.
@retval EFI_SUCCESS The matching handles are outputed successfully.
HandleBufferLength is updated with the actual length.
@retval EFI_BUFFER_TOO_SMALL The HandleBufferLength parameter
indicates that Handle is too
small to support the number of
handles. HandleBufferLength is
updated with a value that will
enable the data to fit.
@retval EFI_NOT_FOUND No matching handle could be found in database.
@retval EFI_INVALID_PARAMETER Handle or HandleBufferLength was NULL.
@retval EFI_INVALID_PARAMETER PackageType is not a EFI_HII_PACKAGE_TYPE_GUID but
PackageGuid is not NULL, PackageType is a EFI_HII_
PACKAGE_TYPE_GUID but PackageGuid is NULL.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_HII_DATABASE_LIST_PACKS)(
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN UINT8 PackageType,
IN CONST EFI_GUID *PackageGuid,
IN OUT UINTN *HandleBufferLength,
OUT EFI_HII_HANDLE *Handle
);
/**
This function will export one or all package lists in the
database to a buffer. For each package list exported, this
function will call functions registered with EXPORT_PACK and
then copy the package list to the buffer. The registered
functions may call EFI_HII_DATABASE_PROTOCOL.UpdatePackageList()
to modify the package list before it is copied to the buffer. If
the specified BufferSize is too small, then the status
EFI_OUT_OF_RESOURCES will be returned and the actual package
size will be returned in BufferSize.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param Handle An EFI_HII_HANDLE that corresponds to the
desired package list in the HII database to
export or NULL to indicate all package lists
should be exported.
@param BufferSize On input, a pointer to the length of the
buffer. On output, the length of the
buffer that is required for the exported
data.
@param Buffer A pointer to a buffer that will contain the
results of the export function.
@retval EFI_SUCCESS Package exported.
@retval EFI_OUT_OF_RESOURCES BufferSize is too small to hold the package.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_HII_DATABASE_EXPORT_PACKS)(
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN EFI_HII_HANDLE Handle,
IN OUT UINTN *BufferSize,
OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer
);
/**
This function registers a function which will be called when
specified actions related to packages of the specified type
occur in the HII database. By registering a function, other
HII-related drivers are notified when specific package types
are added, removed or updated in the HII database. Each driver
or application which registers a notification should use
EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify() before
exiting.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param PackageType The package type. See
EFI_HII_PACKAGE_TYPE_x in EFI_HII_PACKAGE_HEADER.
@param PackageGuid If PackageType is
EFI_HII_PACKAGE_TYPE_GUID, then this is
the pointer to the GUID which must match
the Guid field of
EFI_HII_PACKAGE_GUID_HEADER. Otherwise, it
must be NULL.
@param PackageNotifyFn Points to the function to be called
when the event specified by
NotificationType occurs. See
EFI_HII_DATABASE_NOTIFY.
@param NotifyType Describes the types of notification which
this function will be receiving. See
EFI_HII_DATABASE_NOTIFY_TYPE for a
list of types.
@param NotifyHandle Points to the unique handle assigned to
the registered notification. Can be used
in EFI_HII_DATABASE_PROTOCOL.UnregisterPack
to stop notifications.
@retval EFI_SUCCESS Notification registered successfully.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary
data structures.
@retval EFI_INVALID_PARAMETER PackageGuid is not NULL when
PackageType is not
EFI_HII_PACKAGE_TYPE_GUID.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_HII_DATABASE_REGISTER_NOTIFY)(
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN UINT8 PackageType,
IN CONST EFI_GUID *PackageGuid,
IN EFI_HII_DATABASE_NOTIFY PackageNotifyFn,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
OUT EFI_HANDLE *NotifyHandle
);
/**
Removes the specified HII database package-related notification.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param NotificationHandle The handle of the notification
function being unregistered.
@retval EFI_SUCCESS Successsfully unregistered the notification.
@retval EFI_NOT_FOUND The incoming notification handle does not exist
in the current hii database.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_HII_DATABASE_UNREGISTER_NOTIFY)(
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN EFI_HANDLE NotificationHandle
);
/**
This routine retrieves an array of GUID values for each keyboard
layout that was previously registered in the system.
@param This A pointer to the EFI_HII_PROTOCOL instance.
@param KeyGuidBufferLength On input, a pointer to the length
of the keyboard GUID buffer. On
output, the length of the handle
buffer that is required for the
handles found.
@param KeyGuidBuffer An array of keyboard layout GUID
instances returned.
@retval EFI_SUCCESS KeyGuidBuffer was updated successfully.
@retval EFI_BUFFER_TOO_SMALL The KeyGuidBufferLength
parameter indicates that
KeyGuidBuffer is too small to
support the number of GUIDs.
KeyGuidBufferLength is updated
with a value that will enable
the data to fit.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_HII_FIND_KEYBOARD_LAYOUTS)(
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN OUT UINT16 *KeyGuidBufferLength,
OUT EFI_GUID *KeyGuidBuffer
);
/**
This routine retrieves the requested keyboard layout. The layout
is a physical description of the keys on a keyboard, and the
character(s) that are associated with a particular set of key
strokes.
@param This A pointer to the EFI_HII_PROTOCOL instance.
@param KeyGuid A pointer to the unique ID associated with a
given keyboard layout. If KeyGuid is NULL then
the current layout will be retrieved.
@param KeyboardLayoutLength On input, a pointer to the length of the
KeyboardLayout buffer. On output, the length of
the data placed into KeyboardLayout.
@param KeyboardLayout A pointer to a buffer containing the
retrieved keyboard layout.
@retval EFI_SUCCESS The keyboard layout was retrieved
successfully.
@retval EFI_NOT_FOUND The requested keyboard layout was not found.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_HII_GET_KEYBOARD_LAYOUT)(
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN CONST EFI_GUID *KeyGuid,
IN OUT UINT16 *KeyboardLayoutLength,
OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout
);
/**
This routine sets the default keyboard layout to the one
referenced by KeyGuid. When this routine is called, an event
will be signaled of the EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
group type. This is so that agents which are sensitive to the
current keyboard layout being changed can be notified of this
change.
@param This A pointer to the EFI_HII_PROTOCOL instance.
@param KeyGuid A pointer to the unique ID associated with a
given keyboard layout.
@retval EFI_SUCCESS The current keyboard layout was successfully set.
@retval EFI_NOT_FOUND The referenced keyboard layout was not
found, so action was taken.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_HII_SET_KEYBOARD_LAYOUT)(
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN CONST EFI_GUID *KeyGuid
);
/**
Return the EFI handle associated with a package list.
@param This A pointer to the EFI_HII_PROTOCOL instance.
@param PackageListHandle An EFI_HII_HANDLE that corresponds
to the desired package list in the
HIIdatabase.
@param DriverHandle On return, contains the EFI_HANDLE which
was registered with the package list in
NewPackageList().
@retval EFI_SUCCESS The DriverHandle was returned successfully.
@retval EFI_INVALID_PARAMETER The PackageListHandle was not valid.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_HII_DATABASE_GET_PACK_HANDLE)(
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN EFI_HII_HANDLE PackageListHandle,
OUT EFI_HANDLE *DriverHandle
);
///
/// Database manager for HII-related data structures.
///
struct _EFI_HII_DATABASE_PROTOCOL {
EFI_HII_DATABASE_NEW_PACK NewPackageList;
EFI_HII_DATABASE_REMOVE_PACK RemovePackageList;
EFI_HII_DATABASE_UPDATE_PACK UpdatePackageList;
EFI_HII_DATABASE_LIST_PACKS ListPackageLists;
EFI_HII_DATABASE_EXPORT_PACKS ExportPackageLists;
EFI_HII_DATABASE_REGISTER_NOTIFY RegisterPackageNotify;
EFI_HII_DATABASE_UNREGISTER_NOTIFY UnregisterPackageNotify;
EFI_HII_FIND_KEYBOARD_LAYOUTS FindKeyboardLayouts;
EFI_HII_GET_KEYBOARD_LAYOUT GetKeyboardLayout;
EFI_HII_SET_KEYBOARD_LAYOUT SetKeyboardLayout;
EFI_HII_DATABASE_GET_PACK_HANDLE GetPackageListHandle;
};
extern EFI_GUID gEfiHiiDatabaseProtocolGuid;
#endif

View File

@ -0,0 +1,140 @@
#ifndef _IPXE_EFI_HII_H
#define _IPXE_EFI_HII_H
/** @file
*
* EFI human interface infrastructure
*/
FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/efi/Uefi/UefiInternalFormRepresentation.h>
#include <ipxe/efi/Guid/MdeModuleHii.h>
/**
* Define an EFI IFR form set type
*
* @v num_class_guids Number of class GUIDs
* @ret type Form set type
*/
#define EFI_IFR_FORM_SET_TYPE( num_class_guids ) \
struct { \
EFI_IFR_FORM_SET FormSet; \
EFI_GUID ClassGuid[num_class_guids]; \
} __attribute__ (( packed ))
/**
* Define an EFI IFR form set
*
* @v guid GUID
* @v title Title string
* @v help Help string
* @v type Form set type (as returned by EFI_IFR_FORM_SET_TYPE())
* @ret ifr Form set
*
* This definition opens a new scope, which must be closed by an
* EFI_IFR_END().
*/
#define EFI_IFR_FORM_SET( guid, title, help, type, ... ) { \
.FormSet = { \
.Header = { \
.OpCode = EFI_IFR_FORM_SET_OP, \
.Length = sizeof ( type ), \
.Scope = 1, \
}, \
.Guid = guid, \
.FormSetTitle = title, \
.Help = help, \
.Flags = ( sizeof ( ( ( type * ) NULL )->ClassGuid ) / \
sizeof ( ( ( type * ) NULL )->ClassGuid[0] ) ), \
}, \
.ClassGuid = { \
__VA_ARGS__ \
}, \
}
/**
* Define an EFI IFR GUID class
*
* @v class Class
* @ret ifr GUID class
*/
#define EFI_IFR_GUID_CLASS( class ) { \
.Header = { \
.OpCode = EFI_IFR_GUID_OP, \
.Length = sizeof ( EFI_IFR_GUID_CLASS ), \
}, \
.Guid = EFI_IFR_TIANO_GUID, \
.ExtendOpCode = EFI_IFR_EXTEND_OP_CLASS, \
.Class = class, \
}
/**
* Define an EFI IFR GUID subclass
*
* @v subclass Subclass
* @ret ifr GUID subclass
*/
#define EFI_IFR_GUID_SUBCLASS( subclass ) { \
.Header = { \
.OpCode = EFI_IFR_GUID_OP, \
.Length = sizeof ( EFI_IFR_GUID_SUBCLASS ), \
}, \
.Guid = EFI_IFR_TIANO_GUID, \
.ExtendOpCode = EFI_IFR_EXTEND_OP_SUBCLASS, \
.SubClass = subclass, \
}
/**
* Define an EFI IFR form
*
* @v formid Form ID
* @v title Title string
* @ret ifr Form
*
* This definition opens a new scope, which must be closed by an
* EFI_IFR_END().
*/
#define EFI_IFR_FORM( formid, title ) { \
.Header = { \
.OpCode = EFI_IFR_FORM_OP, \
.Length = sizeof ( EFI_IFR_FORM ), \
.Scope = 1, \
}, \
.FormId = formid, \
.FormTitle = title, \
}
/**
* Define an EFI IFR text widget
*
* @v prompt Prompt string
* @v help Help string
* @v text Text string
* @ret ifr Text widget
*/
#define EFI_IFR_TEXT( prompt, help, text ) { \
.Header = { \
.OpCode = EFI_IFR_TEXT_OP, \
.Length = sizeof ( EFI_IFR_TEXT ), \
}, \
.Statement = { \
.Prompt = prompt, \
.Help = help, \
}, \
.TextTwo = text, \
}
/**
* Define an EFI IFR end marker
*
* @ret ifr End marker
*/
#define EFI_IFR_END() { \
.Header = { \
.OpCode = EFI_IFR_END_OP, \
.Length = sizeof ( EFI_IFR_END ), \
}, \
}
#endif /* _IPXE_EFI_HII_H */

View File

@ -31,9 +31,13 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/efi/efi_pci.h>
#include <ipxe/efi/efi_driver.h>
#include <ipxe/efi/efi_strings.h>
#include <ipxe/efi/efi_hii.h>
#include <ipxe/efi/Protocol/SimpleNetwork.h>
#include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h>
#include <ipxe/efi/Protocol/DevicePath.h>
#include <ipxe/efi/Protocol/HiiConfigAccess.h>
#include <ipxe/efi/Protocol/HiiDatabase.h>
#include <config/general.h>
/** @file
*
@ -71,6 +75,12 @@ struct efi_snp_device {
unsigned int rx_count_events;
/** The network interface identifier */
EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii;
/** HII configuration access protocol */
EFI_HII_CONFIG_ACCESS_PROTOCOL hii;
/** HII package list */
EFI_HII_PACKAGE_LIST_HEADER *package_list;
/** HII handle */
EFI_HII_HANDLE hii_handle;
/** Device name */
wchar_t name[ sizeof ( ( ( struct net_device * ) NULL )->name ) ];
/** The device path
@ -744,6 +754,339 @@ static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp = {
.Receive = efi_snp_receive,
};
/******************************************************************************
*
* Human Interface Infrastructure
*
******************************************************************************
*/
/** EFI configuration access protocol GUID */
static EFI_GUID efi_hii_config_access_protocol_guid
= EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID;
/** EFI HII database protocol */
static EFI_HII_DATABASE_PROTOCOL *efihii;
EFI_REQUIRE_PROTOCOL ( EFI_HII_DATABASE_PROTOCOL, &efihii );
/** Local GUID used for our EFI SNP formset */
#define EFI_SNP_FORMSET_GUID \
{ 0xc4f84019, 0x6dfd, 0x4a27, \
{ 0x9b, 0x94, 0xb7, 0x2e, 0x1f, 0xbc, 0xad, 0xca } }
/** Form identifiers used for our EFI SNP HII */
enum efi_snp_hii_form_id {
EFI_SNP_FORM = 0x0001, /**< The only form */
};
/** String identifiers used for our EFI SNP HII */
enum efi_snp_hii_string_id {
/* Language name */
EFI_SNP_LANGUAGE_NAME = 0x0001,
/* Formset */
EFI_SNP_FORMSET_TITLE, EFI_SNP_FORMSET_HELP,
/* Product name */
EFI_SNP_PRODUCT_PROMPT, EFI_SNP_PRODUCT_HELP, EFI_SNP_PRODUCT_TEXT,
/* Version */
EFI_SNP_VERSION_PROMPT, EFI_SNP_VERSION_HELP, EFI_SNP_VERSION_TEXT,
/* Driver */
EFI_SNP_DRIVER_PROMPT, EFI_SNP_DRIVER_HELP, EFI_SNP_DRIVER_TEXT,
/* Device */
EFI_SNP_DEVICE_PROMPT, EFI_SNP_DEVICE_HELP, EFI_SNP_DEVICE_TEXT,
/* End of list */
EFI_SNP_MAX_STRING_ID
};
/** EFI SNP formset */
struct efi_snp_formset {
EFI_HII_PACKAGE_HEADER Header;
EFI_IFR_FORM_SET_TYPE(1) FormSet;
EFI_IFR_GUID_CLASS Class;
EFI_IFR_GUID_SUBCLASS SubClass;
EFI_IFR_FORM Form;
EFI_IFR_TEXT ProductText;
EFI_IFR_TEXT VersionText;
EFI_IFR_TEXT DriverText;
EFI_IFR_TEXT DeviceText;
EFI_IFR_END EndForm;
EFI_IFR_END EndFormSet;
} __attribute__ (( packed )) efi_snp_formset = {
.Header = {
.Length = sizeof ( efi_snp_formset ),
.Type = EFI_HII_PACKAGE_FORMS,
},
.FormSet = EFI_IFR_FORM_SET ( EFI_SNP_FORMSET_GUID,
EFI_SNP_FORMSET_TITLE,
EFI_SNP_FORMSET_HELP,
typeof ( efi_snp_formset.FormSet ),
EFI_HII_PLATFORM_SETUP_FORMSET_GUID ),
.Class = EFI_IFR_GUID_CLASS ( EFI_NETWORK_DEVICE_CLASS ),
.SubClass = EFI_IFR_GUID_SUBCLASS ( 0x03 ),
.Form = EFI_IFR_FORM ( EFI_SNP_FORM, EFI_SNP_FORMSET_TITLE ),
.ProductText = EFI_IFR_TEXT ( EFI_SNP_PRODUCT_PROMPT,
EFI_SNP_PRODUCT_HELP,
EFI_SNP_PRODUCT_TEXT ),
.VersionText = EFI_IFR_TEXT ( EFI_SNP_VERSION_PROMPT,
EFI_SNP_VERSION_HELP,
EFI_SNP_VERSION_TEXT ),
.DriverText = EFI_IFR_TEXT ( EFI_SNP_DRIVER_PROMPT,
EFI_SNP_DRIVER_HELP,
EFI_SNP_DRIVER_TEXT ),
.DeviceText = EFI_IFR_TEXT ( EFI_SNP_DEVICE_PROMPT,
EFI_SNP_DEVICE_HELP,
EFI_SNP_DEVICE_TEXT ),
.EndForm = EFI_IFR_END(),
.EndFormSet = EFI_IFR_END(),
};
/**
* Generate EFI SNP string
*
* @v wbuf Buffer
* @v swlen Size of buffer (in wide characters)
* @v snpdev SNP device
* @ret wlen Length of string (in wide characters)
*/
static int efi_snp_string ( wchar_t *wbuf, ssize_t swlen,
enum efi_snp_hii_string_id id,
struct efi_snp_device *snpdev ) {
struct net_device *netdev = snpdev->netdev;
struct device *dev = netdev->dev;
switch ( id ) {
case EFI_SNP_LANGUAGE_NAME:
return efi_ssnprintf ( wbuf, swlen, "English" );
case EFI_SNP_FORMSET_TITLE:
return efi_ssnprintf ( wbuf, swlen, "%s (%s)",
( PRODUCT_NAME[0] ?
PRODUCT_NAME : PRODUCT_SHORT_NAME ),
netdev_addr ( netdev ) );
case EFI_SNP_FORMSET_HELP:
return efi_ssnprintf ( wbuf, swlen,
"Configure " PRODUCT_SHORT_NAME );
case EFI_SNP_PRODUCT_PROMPT:
return efi_ssnprintf ( wbuf, swlen, "Name" );
case EFI_SNP_PRODUCT_HELP:
return efi_ssnprintf ( wbuf, swlen, "Firmware product name" );
case EFI_SNP_PRODUCT_TEXT:
return efi_ssnprintf ( wbuf, swlen, "%s",
( PRODUCT_NAME[0] ?
PRODUCT_NAME : PRODUCT_SHORT_NAME ) );
case EFI_SNP_VERSION_PROMPT:
return efi_ssnprintf ( wbuf, swlen, "Version" );
case EFI_SNP_VERSION_HELP:
return efi_ssnprintf ( wbuf, swlen, "Firmware version" );
case EFI_SNP_VERSION_TEXT:
return efi_ssnprintf ( wbuf, swlen, VERSION );
case EFI_SNP_DRIVER_PROMPT:
return efi_ssnprintf ( wbuf, swlen, "Driver" );
case EFI_SNP_DRIVER_HELP:
return efi_ssnprintf ( wbuf, swlen, "Firmware driver" );
case EFI_SNP_DRIVER_TEXT:
return efi_ssnprintf ( wbuf, swlen, "%s", dev->driver_name );
case EFI_SNP_DEVICE_PROMPT:
return efi_ssnprintf ( wbuf, swlen, "Device" );
case EFI_SNP_DEVICE_HELP:
return efi_ssnprintf ( wbuf, swlen, "Hardware device" );
case EFI_SNP_DEVICE_TEXT:
return efi_ssnprintf ( wbuf, swlen, "%s", dev->name );
default:
assert ( 0 );
return 0;
}
}
/**
* Generate EFI SNP string package
*
* @v strings String package header buffer
* @v max_len Buffer length
* @v snpdev SNP device
* @ret len Length of string package
*/
static int efi_snp_strings ( EFI_HII_STRING_PACKAGE_HDR *strings,
size_t max_len, struct efi_snp_device *snpdev ) {
static const char language[] = "en-us";
void *buf = strings;
ssize_t remaining = max_len;
size_t hdrsize;
EFI_HII_SIBT_STRING_UCS2_BLOCK *string;
ssize_t wremaining;
size_t string_wlen;
unsigned int id;
EFI_HII_STRING_BLOCK *end;
size_t len;
/* Calculate header size */
hdrsize = ( offsetof ( typeof ( *strings ), Language ) +
sizeof ( language ) );
buf += hdrsize;
remaining -= hdrsize;
/* Fill in strings */
for ( id = 1 ; id < EFI_SNP_MAX_STRING_ID ; id++ ) {
string = buf;
if ( remaining >= ( ( ssize_t ) sizeof ( string->Header ) ) )
string->Header.BlockType = EFI_HII_SIBT_STRING_UCS2;
buf += offsetof ( typeof ( *string ), StringText );
remaining -= offsetof ( typeof ( *string ), StringText );
wremaining = ( remaining /
( ( ssize_t ) sizeof ( string->StringText[0] )));
assert ( ! ( ( remaining <= 0 ) && ( wremaining > 0 ) ) );
string_wlen = efi_snp_string ( string->StringText, wremaining,
id, snpdev );
buf += ( ( string_wlen + 1 /* wNUL */ ) *
sizeof ( string->StringText[0] ) );
remaining -= ( ( string_wlen + 1 /* wNUL */ ) *
sizeof ( string->StringText[0] ) );
}
/* Fill in end marker */
end = buf;
if ( remaining >= ( ( ssize_t ) sizeof ( *end ) ) )
end->BlockType = EFI_HII_SIBT_END;
buf += sizeof ( *end );
remaining -= sizeof ( *end );
/* Calculate overall length */
len = ( max_len - remaining );
/* Fill in string package header */
if ( strings ) {
memset ( strings, 0, sizeof ( *strings ) );
strings->Header.Length = len;
strings->Header.Type = EFI_HII_PACKAGE_STRINGS;
strings->HdrSize = hdrsize;
strings->StringInfoOffset = hdrsize;
strings->LanguageName = EFI_SNP_LANGUAGE_NAME;
memcpy ( strings->Language, language, sizeof ( language ) );
}
return len;
}
/**
* Generate EFI SNP package list
*
* @v snpdev SNP device
* @ret package_list Package list, or NULL on error
*
* The package list is allocated using malloc(), and must eventually
* be freed by the caller.
*/
static EFI_HII_PACKAGE_LIST_HEADER *
efi_snp_package_list ( struct efi_snp_device *snpdev ) {
size_t strings_len = efi_snp_strings ( NULL, 0, snpdev );
struct {
EFI_HII_PACKAGE_LIST_HEADER header;
struct efi_snp_formset formset;
union {
EFI_HII_STRING_PACKAGE_HDR strings;
uint8_t pad[strings_len];
} __attribute__ (( packed )) strings;
EFI_HII_PACKAGE_HEADER end;
} __attribute__ (( packed )) *package_list;
/* Allocate package list */
package_list = zalloc ( sizeof ( *package_list ) );
if ( ! package_list )
return NULL;
/* Populate package list */
memcpy ( &package_list->header.PackageListGuid,
&efi_snp_formset.FormSet.FormSet.Guid,
sizeof ( package_list->header.PackageListGuid ) );
package_list->header.PackageLength = sizeof ( *package_list );
memcpy ( &package_list->formset, &efi_snp_formset,
sizeof ( package_list->formset ) );
efi_snp_strings ( &package_list->strings.strings,
sizeof ( package_list->strings ), snpdev );
package_list->end.Length = sizeof ( package_list->end );
package_list->end.Type = EFI_HII_PACKAGE_END;
return &package_list->header;
}
/**
* Fetch configuration
*
* @v hii HII configuration access protocol
* @v request Configuration to fetch
* @ret progress Progress made through configuration to fetch
* @ret results Query results
* @ret efirc EFI status code
*/
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 __unused ) {
struct efi_snp_device *snpdev =
container_of ( hii, struct efi_snp_device, hii );
DBGC ( snpdev, "SNPDEV %p ExtractConfig\n", snpdev );
*progress = request;
return EFI_INVALID_PARAMETER;
}
/**
* Store configuration
*
* @v hii HII configuration access protocol
* @v config Configuration to store
* @ret progress Progress made through configuration to store
* @ret efirc EFI status code
*/
static EFI_STATUS EFIAPI
efi_snp_hii_route_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii,
EFI_STRING config, EFI_STRING *progress ) {
struct efi_snp_device *snpdev =
container_of ( hii, struct efi_snp_device, hii );
DBGC ( snpdev, "SNPDEV %p RouteConfig\n", snpdev );
*progress = config;
return EFI_INVALID_PARAMETER;
}
/**
* Handle form actions
*
* @v hii HII configuration access protocol
* @v action Form browser action
* @v question_id Question ID
* @v type Type of value
* @v value Value
* @ret action_request Action requested by driver
* @ret efirc EFI status code
*/
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 ) {
struct efi_snp_device *snpdev =
container_of ( hii, struct efi_snp_device, hii );
DBGC ( snpdev, "SNPDEV %p Callback\n", snpdev );
return EFI_UNSUPPORTED;
}
/** HII configuration access protocol */
static EFI_HII_CONFIG_ACCESS_PROTOCOL efi_snp_device_hii = {
.ExtractConfig = efi_snp_hii_extract_config,
.RouteConfig = efi_snp_hii_route_config,
.Callback = efi_snp_hii_callback,
};
/******************************************************************************
*
* iPXE network driver
*
******************************************************************************
*/
/**
* Locate SNP device corresponding to network device
*
@ -830,6 +1173,9 @@ static int efi_snp_probe ( struct net_device *netdev ) {
strncpy ( snpdev->nii.StringId, "iPXE",
sizeof ( snpdev->nii.StringId ) );
/* Populate the HII configuration access structure */
memcpy ( &snpdev->hii, &efi_snp_device_hii, sizeof ( snpdev->hii ) );
/* Populate the device name */
efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) /
sizeof ( snpdev->name[0] ) ),
@ -858,6 +1204,7 @@ static int efi_snp_probe ( struct net_device *netdev ) {
&efi_device_path_protocol_guid, &snpdev->path,
&efi_nii_protocol_guid, &snpdev->nii,
&efi_nii31_protocol_guid, &snpdev->nii,
&efi_hii_config_access_protocol_guid, &snpdev->hii,
NULL ) ) != 0 ) {
DBGC ( snpdev, "SNPDEV %p could not install protocols: "
"%s\n", snpdev, efi_strerror ( efirc ) );
@ -874,6 +1221,25 @@ static int efi_snp_probe ( struct net_device *netdev ) {
goto err_efipci_child_add;
}
/* Create HII package list */
snpdev->package_list = efi_snp_package_list ( snpdev );
if ( ! snpdev->package_list ) {
DBGC ( snpdev, "SNPDEV %p could not create HII package list\n",
snpdev );
rc = -ENOMEM;
goto err_create_hii;
}
/* Add HII packages */
if ( ( efirc = efihii->NewPackageList ( efihii, snpdev->package_list,
snpdev->handle,
&snpdev->hii_handle ) ) != 0 ) {
DBGC ( snpdev, "SNPDEV %p could not add HII packages: %s\n",
snpdev, efi_strerror ( efirc ) );
rc = EFIRC_TO_RC ( efirc );
goto err_register_hii;
}
/* Add to list of SNP devices */
list_add ( &snpdev->list, &efi_snp_devices );
@ -881,6 +1247,10 @@ static int efi_snp_probe ( struct net_device *netdev ) {
snpdev, netdev->name, snpdev->handle );
return 0;
efihii->RemovePackageList ( efihii, snpdev->hii_handle );
err_register_hii:
free ( snpdev->package_list );
err_create_hii:
efipci_child_del ( efipci, snpdev->handle );
err_efipci_child_add:
bs->UninstallMultipleProtocolInterfaces (
@ -889,6 +1259,7 @@ static int efi_snp_probe ( struct net_device *netdev ) {
&efi_device_path_protocol_guid, &snpdev->path,
&efi_nii_protocol_guid, &snpdev->nii,
&efi_nii31_protocol_guid, &snpdev->nii,
&efi_hii_config_access_protocol_guid, &snpdev->hii,
NULL );
err_install_protocol_interface:
bs->CloseEvent ( snpdev->snp.WaitForPacket );
@ -927,6 +1298,8 @@ static void efi_snp_remove ( struct net_device *netdev ) {
}
/* Uninstall the SNP */
efihii->RemovePackageList ( efihii, snpdev->hii_handle );
free ( snpdev->package_list );
efipci_child_del ( snpdev->efipci, snpdev->handle );
list_del ( &snpdev->list );
bs->UninstallMultipleProtocolInterfaces (
@ -935,6 +1308,7 @@ static void efi_snp_remove ( struct net_device *netdev ) {
&efi_device_path_protocol_guid, &snpdev->path,
&efi_nii_protocol_guid, &snpdev->nii,
&efi_nii31_protocol_guid, &snpdev->nii,
&efi_hii_config_access_protocol_guid, &snpdev->hii,
NULL );
bs->CloseEvent ( snpdev->snp.WaitForPacket );
netdev_put ( snpdev->netdev );