iPXE
efi_hii.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 #include <stdlib.h>
00027 #include <stddef.h>
00028 #include <stdarg.h>
00029 #include <string.h>
00030 #include <ipxe/efi/efi.h>
00031 #include <ipxe/efi/efi_strings.h>
00032 #include <ipxe/efi/efi_hii.h>
00033 
00034 /** Tiano GUID */
00035 static const EFI_GUID tiano_guid = EFI_IFR_TIANO_GUID;
00036 
00037 /**
00038  * Add string to IFR builder
00039  *
00040  * @v ifr               IFR builder
00041  * @v fmt               Format string
00042  * @v ...               Arguments
00043  * @ret string_id       String identifier, or zero on failure
00044  */
00045 unsigned int efi_ifr_string ( struct efi_ifr_builder *ifr, const char *fmt,
00046                               ... ) {
00047         EFI_HII_STRING_BLOCK *new_strings;
00048         EFI_HII_SIBT_STRING_UCS2_BLOCK *ucs2;
00049         size_t new_strings_len;
00050         va_list args;
00051         size_t len;
00052         unsigned int string_id;
00053 
00054         /* Do nothing if a previous allocation has failed */
00055         if ( ifr->failed )
00056                 return 0;
00057 
00058         /* Calculate string length */
00059         va_start ( args, fmt );
00060         len = ( efi_vsnprintf ( NULL, 0, fmt, args ) + 1 /* wNUL */ );
00061         va_end ( args );
00062 
00063         /* Reallocate strings */
00064         new_strings_len = ( ifr->strings_len +
00065                             offsetof ( typeof ( *ucs2 ), StringText ) +
00066                             ( len * sizeof ( ucs2->StringText[0] ) ) );
00067         new_strings = realloc ( ifr->strings, new_strings_len );
00068         if ( ! new_strings ) {
00069                 ifr->failed = 1;
00070                 return 0;
00071         }
00072         ucs2 = ( ( ( void * ) new_strings ) + ifr->strings_len );
00073         ifr->strings = new_strings;
00074         ifr->strings_len = new_strings_len;
00075 
00076         /* Fill in string */
00077         ucs2->Header.BlockType = EFI_HII_SIBT_STRING_UCS2;
00078         va_start ( args, fmt );
00079         efi_vsnprintf ( ucs2->StringText, len, fmt, args );
00080         va_end ( args );
00081 
00082         /* Allocate string ID */
00083         string_id = ++(ifr->string_id);
00084 
00085         DBGC ( ifr, "IFR %p string %#04x is \"%ls\"\n",
00086                ifr, string_id, ucs2->StringText );
00087         return string_id;
00088 }
00089 
00090 /**
00091  * Add IFR opcode to IFR builder
00092  *
00093  * @v ifr               IFR builder
00094  * @v opcode            Opcode
00095  * @v len               Opcode length
00096  * @ret op              Opcode, or NULL
00097  */
00098 static void * efi_ifr_op ( struct efi_ifr_builder *ifr, unsigned int opcode,
00099                            size_t len ) {
00100         EFI_IFR_OP_HEADER *new_ops;
00101         EFI_IFR_OP_HEADER *op;
00102         size_t new_ops_len;
00103 
00104         /* Do nothing if a previous allocation has failed */
00105         if ( ifr->failed )
00106                 return NULL;
00107 
00108         /* Reallocate opcodes */
00109         new_ops_len = ( ifr->ops_len + len );
00110         new_ops = realloc ( ifr->ops, new_ops_len );
00111         if ( ! new_ops ) {
00112                 ifr->failed = 1;
00113                 return NULL;
00114         }
00115         op = ( ( ( void * ) new_ops ) + ifr->ops_len );
00116         ifr->ops = new_ops;
00117         ifr->ops_len = new_ops_len;
00118 
00119         /* Fill in opcode header */
00120         memset ( op, 0, len );
00121         op->OpCode = opcode;
00122         op->Length = len;
00123 
00124         return op;
00125 }
00126 
00127 /**
00128  * Add end opcode to IFR builder
00129  *
00130  * @v ifr               IFR builder
00131  */
00132 void efi_ifr_end_op ( struct efi_ifr_builder *ifr ) {
00133         size_t dispaddr = ifr->ops_len;
00134         EFI_IFR_END *end;
00135 
00136         /* Add opcode */
00137         end = efi_ifr_op ( ifr, EFI_IFR_END_OP, sizeof ( *end ) );
00138 
00139         DBGC ( ifr, "IFR %p end\n", ifr );
00140         DBGC2_HDA ( ifr, dispaddr, end, sizeof ( *end ) );
00141 }
00142 
00143 /**
00144  * Add false opcode to IFR builder
00145  *
00146  * @v ifr               IFR builder
00147  */
00148 void efi_ifr_false_op ( struct efi_ifr_builder *ifr ) {
00149         size_t dispaddr = ifr->ops_len;
00150         EFI_IFR_FALSE *false;
00151 
00152         /* Add opcode */
00153         false = efi_ifr_op ( ifr, EFI_IFR_FALSE_OP, sizeof ( *false ) );
00154 
00155         DBGC ( ifr, "IFR %p false\n", ifr );
00156         DBGC2_HDA ( ifr, dispaddr, false, sizeof ( *false ) );
00157 }
00158 
00159 /**
00160  * Add form opcode to IFR builder
00161  *
00162  * @v ifr               IFR builder
00163  * @v title_id          Title string identifier
00164  * @ret form_id         Form identifier
00165  */
00166 unsigned int efi_ifr_form_op ( struct efi_ifr_builder *ifr,
00167                                unsigned int title_id ) {
00168         size_t dispaddr = ifr->ops_len;
00169         EFI_IFR_FORM *form;
00170 
00171         /* Add opcode */
00172         form = efi_ifr_op ( ifr, EFI_IFR_FORM_OP, sizeof ( *form ) );
00173         if ( ! form )
00174                 return 0;
00175         form->Header.Scope = 1;
00176         form->FormId = ++(ifr->form_id);
00177         form->FormTitle = title_id;
00178 
00179         DBGC ( ifr, "IFR %p name/value store %#04x title %#04x\n",
00180                ifr, form->FormId, title_id );
00181         DBGC2_HDA ( ifr, dispaddr, form, sizeof ( *form ) );
00182         return form->FormId;
00183 }
00184 
00185 /**
00186  * Add formset opcode to IFR builder
00187  *
00188  * @v ifr               IFR builder
00189  * @v guid              GUID
00190  * @v title_id          Title string identifier
00191  * @v help_id           Help string identifier
00192  * @v ...               Class GUIDs (terminated by NULL)
00193  */
00194 void efi_ifr_form_set_op ( struct efi_ifr_builder *ifr, const EFI_GUID *guid,
00195                            unsigned int title_id, unsigned int help_id, ... ) {
00196         size_t dispaddr = ifr->ops_len;
00197         EFI_IFR_FORM_SET *formset;
00198         EFI_GUID *class_guid;
00199         unsigned int num_class_guids = 0;
00200         size_t len;
00201         va_list args;
00202 
00203         /* Count number of class GUIDs */
00204         va_start ( args, help_id );
00205         while ( va_arg ( args, const EFI_GUID * ) != NULL )
00206                 num_class_guids++;
00207         va_end ( args );
00208 
00209         /* Add opcode */
00210         len = ( sizeof ( *formset ) +
00211                 ( num_class_guids * sizeof ( *class_guid ) ) );
00212         formset = efi_ifr_op ( ifr, EFI_IFR_FORM_SET_OP, len );
00213         if ( ! formset )
00214                 return;
00215         formset->Header.Scope = 1;
00216         memcpy ( &formset->Guid, guid, sizeof ( formset->Guid ) );
00217         formset->FormSetTitle = title_id;
00218         formset->Help = help_id;
00219         formset->Flags = num_class_guids;
00220 
00221         /* Add class GUIDs */
00222         class_guid = ( ( ( void * ) formset ) + sizeof ( *formset ) );
00223         va_start ( args, help_id );
00224         while ( num_class_guids-- ) {
00225                 memcpy ( class_guid++, va_arg ( args, const EFI_GUID * ),
00226                          sizeof ( *class_guid ) );
00227         }
00228         va_end ( args );
00229 
00230         DBGC ( ifr, "IFR %p formset title %#04x help %#04x\n",
00231                ifr, title_id, help_id );
00232         DBGC2_HDA ( ifr, dispaddr, formset, len );
00233 }
00234 
00235 /**
00236  * Add get opcode to IFR builder
00237  *
00238  * @v ifr               IFR builder
00239  * @v varstore_id       Variable store identifier
00240  * @v varstore_info     Variable string identifier or offset
00241  * @v varstore_type     Variable type
00242  */
00243 void efi_ifr_get_op ( struct efi_ifr_builder *ifr, unsigned int varstore_id,
00244                       unsigned int varstore_info, unsigned int varstore_type ) {
00245         size_t dispaddr = ifr->ops_len;
00246         EFI_IFR_GET *get;
00247 
00248         /* Add opcode */
00249         get = efi_ifr_op ( ifr, EFI_IFR_GET_OP, sizeof ( *get ) );
00250         get->VarStoreId = varstore_id;
00251         get->VarStoreInfo.VarName = varstore_info;
00252         get->VarStoreType = varstore_type;
00253 
00254         DBGC ( ifr, "IFR %p get varstore %#04x:%#04x type %#02x\n",
00255                ifr, varstore_id, varstore_info, varstore_type );
00256         DBGC2_HDA ( ifr, dispaddr, get, sizeof ( *get ) );
00257 }
00258 
00259 /**
00260  * Add GUID class opcode to IFR builder
00261  *
00262  * @v ifr               IFR builder
00263  * @v class             Class
00264  */
00265 void efi_ifr_guid_class_op ( struct efi_ifr_builder *ifr, unsigned int class ) {
00266         size_t dispaddr = ifr->ops_len;
00267         EFI_IFR_GUID_CLASS *guid_class;
00268 
00269         /* Add opcode */
00270         guid_class = efi_ifr_op ( ifr, EFI_IFR_GUID_OP,
00271                                   sizeof ( *guid_class ) );
00272         if ( ! guid_class )
00273                 return;
00274         memcpy ( &guid_class->Guid, &tiano_guid, sizeof ( guid_class->Guid ) );
00275         guid_class->ExtendOpCode = EFI_IFR_EXTEND_OP_CLASS;
00276         guid_class->Class = class;
00277 
00278         DBGC ( ifr, "IFR %p GUID class %#02x\n", ifr, class );
00279         DBGC2_HDA ( ifr, dispaddr, guid_class, sizeof ( *guid_class ) );
00280 }
00281 
00282 /**
00283  * Add GUID subclass opcode to IFR builder
00284  *
00285  * @v ifr               IFR builder
00286  * @v subclass          Subclass
00287  */
00288 void efi_ifr_guid_subclass_op ( struct efi_ifr_builder *ifr,
00289                                 unsigned int subclass ) {
00290         size_t dispaddr = ifr->ops_len;
00291         EFI_IFR_GUID_SUBCLASS *guid_subclass;
00292 
00293         /* Add opcode */
00294         guid_subclass = efi_ifr_op ( ifr, EFI_IFR_GUID_OP,
00295                                      sizeof ( *guid_subclass ) );
00296         if ( ! guid_subclass )
00297                 return;
00298         memcpy ( &guid_subclass->Guid, &tiano_guid,
00299                  sizeof ( guid_subclass->Guid ) );
00300         guid_subclass->ExtendOpCode = EFI_IFR_EXTEND_OP_SUBCLASS;
00301         guid_subclass->SubClass = subclass;
00302 
00303         DBGC ( ifr, "IFR %p GUID subclass %#02x\n", ifr, subclass );
00304         DBGC2_HDA ( ifr, dispaddr, guid_subclass, sizeof ( *guid_subclass ) );
00305 }
00306 
00307 /**
00308  * Add numeric opcode to IFR builder
00309  *
00310  * @v ifr               IFR builder
00311  * @v prompt_id         Prompt string identifier
00312  * @v help_id           Help string identifier
00313  * @v question_id       Question identifier
00314  * @v varstore_id       Variable store identifier
00315  * @v varstore_info     Variable string identifier or offset
00316  * @v vflags            Variable flags
00317  * @v min_value         Minimum value
00318  * @v max_value         Maximum value
00319  * @v step              Step
00320  * @v flags             Flags
00321  */
00322 void efi_ifr_numeric_op ( struct efi_ifr_builder *ifr, unsigned int prompt_id,
00323                           unsigned int help_id, unsigned int question_id,
00324                           unsigned int varstore_id, unsigned int varstore_info,
00325                           unsigned int vflags, unsigned long min_value,
00326                           unsigned long max_value, unsigned int step,
00327                           unsigned int flags ) {
00328         size_t dispaddr = ifr->ops_len;
00329         EFI_IFR_NUMERIC *numeric;
00330         unsigned int size;
00331 
00332         /* Add opcode */
00333         numeric = efi_ifr_op ( ifr, EFI_IFR_NUMERIC_OP, sizeof ( *numeric ) );
00334         if ( ! numeric )
00335                 return;
00336         numeric->Question.Header.Prompt = prompt_id;
00337         numeric->Question.Header.Help = help_id;
00338         numeric->Question.QuestionId = question_id;
00339         numeric->Question.VarStoreId = varstore_id;
00340         numeric->Question.VarStoreInfo.VarName = varstore_info;
00341         numeric->Question.Flags = vflags;
00342         size = ( flags & EFI_IFR_NUMERIC_SIZE );
00343         switch ( size ) {
00344         case EFI_IFR_NUMERIC_SIZE_1 :
00345                 numeric->data.u8.MinValue = min_value;
00346                 numeric->data.u8.MaxValue = max_value;
00347                 numeric->data.u8.Step = step;
00348                 break;
00349         case EFI_IFR_NUMERIC_SIZE_2 :
00350                 numeric->data.u16.MinValue = min_value;
00351                 numeric->data.u16.MaxValue = max_value;
00352                 numeric->data.u16.Step = step;
00353                 break;
00354         case EFI_IFR_NUMERIC_SIZE_4 :
00355                 numeric->data.u32.MinValue = min_value;
00356                 numeric->data.u32.MaxValue = max_value;
00357                 numeric->data.u32.Step = step;
00358                 break;
00359         case EFI_IFR_NUMERIC_SIZE_8 :
00360                 numeric->data.u64.MinValue = min_value;
00361                 numeric->data.u64.MaxValue = max_value;
00362                 numeric->data.u64.Step = step;
00363                 break;
00364         }
00365 
00366         DBGC ( ifr, "IFR %p numeric prompt %#04x help %#04x question %#04x "
00367                "varstore %#04x:%#04x\n", ifr, prompt_id, help_id, question_id,
00368                varstore_id, varstore_info );
00369         DBGC2_HDA ( ifr, dispaddr, numeric, sizeof ( *numeric ) );
00370 }
00371 
00372 /**
00373  * Add string opcode to IFR builder
00374  *
00375  * @v ifr               IFR builder
00376  * @v prompt_id         Prompt string identifier
00377  * @v help_id           Help string identifier
00378  * @v question_id       Question identifier
00379  * @v varstore_id       Variable store identifier
00380  * @v varstore_info     Variable string identifier or offset
00381  * @v vflags            Variable flags
00382  * @v min_size          Minimum size
00383  * @v max_size          Maximum size
00384  * @v flags             Flags
00385  */
00386 void efi_ifr_string_op ( struct efi_ifr_builder *ifr, unsigned int prompt_id,
00387                          unsigned int help_id, unsigned int question_id,
00388                          unsigned int varstore_id, unsigned int varstore_info,
00389                          unsigned int vflags, unsigned int min_size,
00390                          unsigned int max_size, unsigned int flags ) {
00391         size_t dispaddr = ifr->ops_len;
00392         EFI_IFR_STRING *string;
00393 
00394         /* Add opcode */
00395         string = efi_ifr_op ( ifr, EFI_IFR_STRING_OP, sizeof ( *string ) );
00396         if ( ! string )
00397                 return;
00398         string->Question.Header.Prompt = prompt_id;
00399         string->Question.Header.Help = help_id;
00400         string->Question.QuestionId = question_id;
00401         string->Question.VarStoreId = varstore_id;
00402         string->Question.VarStoreInfo.VarName = varstore_info;
00403         string->Question.Flags = vflags;
00404         string->MinSize = min_size;
00405         string->MaxSize = max_size;
00406         string->Flags = flags;
00407 
00408         DBGC ( ifr, "IFR %p string prompt %#04x help %#04x question %#04x "
00409                "varstore %#04x:%#04x\n", ifr, prompt_id, help_id, question_id,
00410                varstore_id, varstore_info );
00411         DBGC2_HDA ( ifr, dispaddr, string, sizeof ( *string ) );
00412 }
00413 
00414 /**
00415  * Add suppress-if opcode to IFR builder
00416  *
00417  * @v ifr               IFR builder
00418  */
00419 void efi_ifr_suppress_if_op ( struct efi_ifr_builder *ifr ) {
00420         size_t dispaddr = ifr->ops_len;
00421         EFI_IFR_SUPPRESS_IF *suppress_if;
00422 
00423         /* Add opcode */
00424         suppress_if = efi_ifr_op ( ifr, EFI_IFR_SUPPRESS_IF_OP,
00425                                    sizeof ( *suppress_if ) );
00426         suppress_if->Header.Scope = 1;
00427 
00428         DBGC ( ifr, "IFR %p suppress-if\n", ifr );
00429         DBGC2_HDA ( ifr, dispaddr, suppress_if, sizeof ( *suppress_if ) );
00430 }
00431 
00432 /**
00433  * Add text opcode to IFR builder
00434  *
00435  * @v ifr               IFR builder
00436  * @v prompt_id         Prompt string identifier
00437  * @v help_id           Help string identifier
00438  * @v text_id           Text string identifier
00439  */
00440 void efi_ifr_text_op ( struct efi_ifr_builder *ifr, unsigned int prompt_id,
00441                        unsigned int help_id, unsigned int text_id ) {
00442         size_t dispaddr = ifr->ops_len;
00443         EFI_IFR_TEXT *text;
00444 
00445         /* Add opcode */
00446         text = efi_ifr_op ( ifr, EFI_IFR_TEXT_OP, sizeof ( *text ) );
00447         if ( ! text )
00448                 return;
00449         text->Statement.Prompt = prompt_id;
00450         text->Statement.Help = help_id;
00451         text->TextTwo = text_id;
00452 
00453         DBGC ( ifr, "IFR %p text prompt %#04x help %#04x text %#04x\n",
00454                ifr, prompt_id, help_id, text_id );
00455         DBGC2_HDA ( ifr, dispaddr, text, sizeof ( *text ) );
00456 }
00457 
00458 /**
00459  * Add true opcode to IFR builder
00460  *
00461  * @v ifr               IFR builder
00462  */
00463 void efi_ifr_true_op ( struct efi_ifr_builder *ifr ) {
00464         size_t dispaddr = ifr->ops_len;
00465         EFI_IFR_TRUE *true;
00466 
00467         /* Add opcode */
00468         true = efi_ifr_op ( ifr, EFI_IFR_TRUE_OP, sizeof ( *true ) );
00469 
00470         DBGC ( ifr, "IFR %p true\n", ifr );
00471         DBGC2_HDA ( ifr, dispaddr, true, sizeof ( *true ) );
00472 }
00473 
00474 /**
00475  * Add name/value store opcode to IFR builder
00476  *
00477  * @v ifr               IFR builder
00478  * @v guid              GUID
00479  * @ret varstore_id     Variable store identifier, or 0 on failure
00480  */
00481 unsigned int efi_ifr_varstore_name_value_op ( struct efi_ifr_builder *ifr,
00482                                               const EFI_GUID *guid ) {
00483         size_t dispaddr = ifr->ops_len;
00484         EFI_IFR_VARSTORE_NAME_VALUE *varstore;
00485 
00486         /* Add opcode */
00487         varstore = efi_ifr_op ( ifr, EFI_IFR_VARSTORE_NAME_VALUE_OP,
00488                                 sizeof ( *varstore ) );
00489         if ( ! varstore )
00490                 return 0;
00491         varstore->VarStoreId = ++(ifr->varstore_id);
00492         memcpy ( &varstore->Guid, guid, sizeof ( varstore->Guid ) );
00493 
00494         DBGC ( ifr, "IFR %p name/value store %#04x\n",
00495                ifr, varstore->VarStoreId );
00496         DBGC2_HDA ( ifr, dispaddr, varstore, sizeof ( *varstore ) );
00497         return varstore->VarStoreId;
00498 }
00499 
00500 /**
00501  * Free memory used by IFR builder
00502  *
00503  * @v ifr               IFR builder
00504  */
00505 void efi_ifr_free ( struct efi_ifr_builder *ifr ) {
00506 
00507         free ( ifr->ops );
00508         free ( ifr->strings );
00509         memset ( ifr, 0, sizeof ( *ifr ) );
00510 }
00511 
00512 /**
00513  * Construct package list from IFR builder
00514  *
00515  * @v ifr               IFR builder
00516  * @v guid              Package GUID
00517  * @v language          Language
00518  * @v language_id       Language string ID
00519  * @ret package         Package list, or NULL
00520  *
00521  * The package list is allocated using malloc(), and must eventually
00522  * be freed by the caller.  (The caller must also call efi_ifr_free()
00523  * to free the temporary storage used during construction.)
00524  */
00525 EFI_HII_PACKAGE_LIST_HEADER * efi_ifr_package ( struct efi_ifr_builder *ifr,
00526                                                 const EFI_GUID *guid,
00527                                                 const char *language,
00528                                                 unsigned int language_id ) {
00529         struct {
00530                 EFI_HII_PACKAGE_LIST_HEADER header;
00531                 struct {
00532                         EFI_HII_PACKAGE_HEADER header;
00533                         uint8_t data[ifr->ops_len];
00534                 } __attribute__ (( packed )) ops;
00535                 struct {
00536                         union {
00537                                 EFI_HII_STRING_PACKAGE_HDR header;
00538                                 uint8_t pad[offsetof(EFI_HII_STRING_PACKAGE_HDR,
00539                                                      Language) +
00540                                             strlen ( language ) + 1 /* NUL */ ];
00541                         } __attribute__ (( packed )) header;
00542                         uint8_t data[ifr->strings_len];
00543                         EFI_HII_STRING_BLOCK end;
00544                 } __attribute__ (( packed )) strings;
00545                 EFI_HII_PACKAGE_HEADER end;
00546         } __attribute__ (( packed )) *package;
00547 
00548         /* Fail if any previous allocation failed */
00549         if ( ifr->failed )
00550                 return NULL;
00551 
00552         /* Allocate package list */
00553         package = zalloc ( sizeof ( *package ) );
00554         if ( ! package )
00555                 return NULL;
00556 
00557         /* Populate package list */
00558         package->header.PackageLength = sizeof ( *package );
00559         memcpy ( &package->header.PackageListGuid, guid,
00560                  sizeof ( package->header.PackageListGuid ) );
00561         package->ops.header.Length = sizeof ( package->ops );
00562         package->ops.header.Type = EFI_HII_PACKAGE_FORMS;
00563         memcpy ( package->ops.data, ifr->ops, sizeof ( package->ops.data ) );
00564         package->strings.header.header.Header.Length =
00565                 sizeof ( package->strings );
00566         package->strings.header.header.Header.Type =
00567                 EFI_HII_PACKAGE_STRINGS;
00568         package->strings.header.header.HdrSize =
00569                 sizeof ( package->strings.header );
00570         package->strings.header.header.StringInfoOffset =
00571                 sizeof ( package->strings.header );
00572         package->strings.header.header.LanguageName = language_id;
00573         strcpy ( package->strings.header.header.Language, language );
00574         memcpy ( package->strings.data, ifr->strings,
00575                  sizeof ( package->strings.data ) );
00576         package->strings.end.BlockType = EFI_HII_SIBT_END;
00577         package->end.Type = EFI_HII_PACKAGE_END;
00578         package->end.Length = sizeof ( package->end );
00579 
00580         return &package->header;
00581 }
00582