Esempio n. 1
0
char *getpass(const char *Prompt)
{
  BOOLEAN Ascii;
  CHAR16  *ReturnString;

  Ascii = FALSE;

  Print(L"%a", Prompt);

  ReturnString = ShellFileHandleReturnLine (gEfiShellParametersProtocol->StdIn, &Ascii);
  if (ReturnString == NULL) {
    return (NULL);
  }

  ReturnStringAscii = AllocateZeroPool((StrLen(ReturnString)+1)*sizeof(CHAR8));
  if (ReturnStringAscii == NULL) {
    return (NULL);
  }

  UnicodeStrToAsciiStr(ReturnString, ReturnStringAscii);

  FreePool(ReturnString);

  return (ReturnStringAscii);
}
Esempio n. 2
0
/**
  Search for a file given its name coded in Ascii.

  When searching through the files of the volume, if a file is currently not
  open, its name was written on the media and is kept in RAM in the
  "HwDescription.Footer.Filename[]" field of the file's description.

  If a file is currently open, its name might not have been written on the
  media yet, and as the "HwDescription" is a mirror in RAM of what is on the
  media the "HwDescription.Footer.Filename[]" might be outdated. In that case,
  the up to date name of the file is stored in the "Info" field of the file's
  description.

  @param[in]   Instance       Pointer to the description of the volume in which
                              the file has to be search for.
  @param[in]   AsciiFileName  Name of the file.

  @param[out]  File           Pointer to the description of the file if the
                              file was found.

  @retval  EFI_SUCCESS    The file was found.
  @retval  EFI_NOT_FOUND  The file was not found.

**/
EFI_STATUS
BootMonGetFileFromAsciiFileName (
  IN  BOOTMON_FS_INSTANCE   *Instance,
  IN  CHAR8*                AsciiFileName,
  OUT BOOTMON_FS_FILE       **File
  )
{
  LIST_ENTRY       *Entry;
  BOOTMON_FS_FILE  *FileEntry;
  CHAR8            OpenFileAsciiFileName[MAX_NAME_LENGTH];
  CHAR8            *AsciiFileNameToCompare;

  // Go through all the files in the list and return the file handle
  for (Entry = GetFirstNode (&Instance->RootFile->Link);
       !IsNull (&Instance->RootFile->Link, Entry);
       Entry = GetNextNode (&Instance->RootFile->Link, Entry)
       )
  {
    FileEntry = BOOTMON_FS_FILE_FROM_LINK_THIS (Entry);
    if (FileEntry->Info != NULL) {
      UnicodeStrToAsciiStr (FileEntry->Info->FileName, OpenFileAsciiFileName);
      AsciiFileNameToCompare = OpenFileAsciiFileName;
    } else {
      AsciiFileNameToCompare = FileEntry->HwDescription.Footer.Filename;
    }

    if (AsciiStrCmp (AsciiFileNameToCompare, AsciiFileName) == 0) {
      *File = FileEntry;
      return EFI_SUCCESS;
    }
  }
  return EFI_NOT_FOUND;
}
Esempio n. 3
0
/**
  Update the string associated with an existing SMBIOS record.

  This function allows the update of specific SMBIOS strings. The number of valid strings for any
  SMBIOS record is defined by how many strings were present when Add() was called.

  @param[in]    SmbiosHandle    SMBIOS Handle of structure that will have its string updated.
  @param[in]    StringNumber    The non-zero string number of the string to update.
  @param[in]    String          Update the StringNumber string with String.

  @retval EFI_SUCCESS           SmbiosHandle had its StringNumber String updated.
  @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist. Or String is invalid.
  @retval EFI_UNSUPPORTED       String was not added because it is longer than the SMBIOS Table supports.
  @retval EFI_NOT_FOUND         The StringNumber.is not valid for this SMBIOS record.
**/
EFI_STATUS
EFIAPI
SmbiosLibUpdateUnicodeString (
  IN  EFI_SMBIOS_HANDLE     SmbiosHandle,
  IN  SMBIOS_TABLE_STRING   StringNumber,
  IN  CHAR16                *String
  )
{
  EFI_STATUS  Status;
  UINTN       StringIndex;
  CHAR8       *Ascii;

  if (String == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (*String == '\0') {
    // A string with no data is not legal in SMBIOS
    return EFI_INVALID_PARAMETER;
  }

  Ascii = AllocateZeroPool (StrSize (String));
  if (Ascii == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  UnicodeStrToAsciiStr (String, Ascii);

  StringIndex = StringNumber;
  Status = gSmbios->UpdateString (gSmbios, &SmbiosHandle, &StringIndex, Ascii);

  FreePool (Ascii);
  return Status;
}
Esempio n. 4
0
/**
  Fill in SPD_ENTRY_INDEXER through ParamPackage list.

  @param[in, out] Indexer         The pointer to the SPD_ENTRY_INDEXER structure.
  @param[in]      ParamPackage    The pointer to the ParamPackage list.

  @retval EFI_SUCCESS    Filled in SPD_ENTRY_INDEXER successfully.
**/
EFI_STATUS
ConstructSpdIndexer (
  IN OUT SPD_ENTRY_INDEXER    *Indexer,
  IN     LIST_ENTRY           *ParamPackage
  )
{
  EFI_STATUS      Status;
  UINT64          Value64;
  CONST CHAR16    *ValueStr;

  ValueStr = NULL;

  if (ShellCommandLineGetFlag (ParamPackage, L"-i")) {
    ValueStr = ShellCommandLineGetValue (ParamPackage, L"-i");
  } else if (ShellCommandLineGetFlag (ParamPackage, L"-d")) {
    ValueStr = ShellCommandLineGetValue (ParamPackage, L"-d");
  } else if (ShellCommandLineGetFlag (ParamPackage, L"-e")) {
    ValueStr = ShellCommandLineGetValue (ParamPackage, L"-e");
  } else {
    ASSERT (FALSE);
  }

  ASSERT (ValueStr != NULL);

  Value64 = StrToUInteger (ValueStr, &Status);
  if (!EFI_ERROR (Status)) {
    Indexer->Index = (UINTN) Value64;
    Indexer->Name  = NULL;
  } else {
    UnicodeStrToAsciiStr (ValueStr, (CHAR8 *) Indexer->Name);
  }

  return EFI_SUCCESS;
}
Esempio n. 5
0
STATIC
EFI_STATUS
SetFileName (
  IN  BOOTMON_FS_FILE *File,
  IN  CHAR16          *FileNameUnicode
  )
{
  CHAR8                 *FileNameAscii;
  UINT16                 SavedChar;
  UINTN                  FileNameSize;
  BOOTMON_FS_FILE       *SameFile;
  EFI_STATUS             Status;

  // EFI Shell inserts '\' in front of the filename that must be stripped
  if (FileNameUnicode[0] == L'\\') {
    FileNameUnicode++;
  }
  //
  // Convert Unicode into Ascii
  //
  SavedChar = L'\0';
  FileNameSize = StrLen (FileNameUnicode) + 1;
  FileNameAscii = AllocatePool (FileNameSize * sizeof (CHAR8));
  if (FileNameAscii == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  // If Unicode string is too long then truncate it.
  if (FileNameSize > MAX_NAME_LENGTH) {
    SavedChar = FileNameUnicode[MAX_NAME_LENGTH - 1];
    FileNameUnicode[MAX_NAME_LENGTH - 1] = L'\0';
  }
  UnicodeStrToAsciiStr (FileNameUnicode, FileNameAscii);
  // If the unicode string was truncated then restore its original content.
  if (SavedChar != L'\0') {
    FileNameUnicode[MAX_NAME_LENGTH - 1] = SavedChar;
  }

  // If we're changing the file name
  if (AsciiStrCmp (FileNameAscii, File->HwDescription.Footer.Filename) == 0) {
    // No change to filename.
    Status = EFI_SUCCESS;
  } else if (!(File->OpenMode & EFI_FILE_MODE_WRITE)) {
    // You can only change the filename if you open the file for write.
    Status = EFI_ACCESS_DENIED;
  } else if (BootMonGetFileFromAsciiFileName (
                File->Instance,
                File->HwDescription.Footer.Filename,
                &SameFile) != EFI_NOT_FOUND) {
    // A file with that name already exists.
    Status = EFI_ACCESS_DENIED;
  } else {
    // OK, change the filename.
    AsciiStrCpy (FileNameAscii, File->HwDescription.Footer.Filename);
    Status = EFI_SUCCESS;
  }

  FreePool (FileNameAscii);
  return Status;
}
Esempio n. 6
0
/**
  Transmit the HTTP mssage by processing the associated HTTP token.

  @param[in]  Map                The container of TxToken.
  @param[in]  Item               Current item to check against.
  @param[in]  Context            The Token to check againist.

  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
  @retval EFI_SUCCESS            The HTTP message is queued into TCP transmit
                                 queue.

**/
EFI_STATUS
EFIAPI
HttpTcpTransmit (
    IN NET_MAP                *Map,
    IN NET_MAP_ITEM           *Item,
    IN VOID                   *Context
)
{
    HTTP_TOKEN_WRAP           *ValueInItem;
    EFI_STATUS                Status;
    CHAR8                     *RequestStr;
    CHAR8                     *Url;

    ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;
    if (ValueInItem->TcpWrap.IsTxDone) {
        return EFI_SUCCESS;
    }

    //
    // Parse the URI of the remote host.
    //
    Url = AllocatePool (StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1);
    if (Url == NULL) {
        return EFI_OUT_OF_RESOURCES;
    }

    UnicodeStrToAsciiStr (ValueInItem->HttpToken->Message->Data.Request->Url, Url);

    //
    // Create request message.
    //
    RequestStr = HttpGenRequestString (
                     ValueInItem->HttpInstance,
                     ValueInItem->HttpToken->Message,
                     Url
                 );
    FreePool (Url);
    if (RequestStr == NULL) {
        return EFI_OUT_OF_RESOURCES;
    }

    //
    // Transmit the request message.
    //
    Status = HttpTransmitTcp4 (
                 ValueInItem->HttpInstance,
                 ValueInItem,
                 (UINT8*) RequestStr,
                 AsciiStrLen (RequestStr)
             );
    FreePool (RequestStr);
    return Status;
}
Esempio n. 7
0
/** The getenv function searches an environment list, provided by the host
    environment, for a string that matches the string pointed to by name.  The
    set of environment names and the method for altering the environment list
    are determined by the underlying UEFI Shell implementation.

    @return   The getenv function returns a pointer to a string associated with
              the matched list member.  The string pointed to shall not be
              modified by the program, but may be overwritten by a subsequent
              call to the getenv function.  If the specified name cannot be
              found, a null pointer is returned.
**/
char   *getenv(const char *name)
{
  const CHAR16  *EfiEnv;
  char          *retval = NULL;

  (void)AsciiStrToUnicodeStr( name, gMD->UString);
  EfiEnv = ShellGetEnvironmentVariable(gMD->UString);
  if(EfiEnv != NULL) {
    retval = UnicodeStrToAsciiStr( EfiEnv, gMD->ASgetenv);
  }

  return retval;
}
Esempio n. 8
0
CHAR8*
Unicode2Ascii (
  CONST CHAR16* UnicodeStr
)
{
  CHAR8* AsciiStr = AllocatePool((StrLen (UnicodeStr) + 1) * sizeof (CHAR8));
  if (AsciiStr == NULL) {
    return NULL;
  }

  UnicodeStrToAsciiStr(UnicodeStr, AsciiStr);

  return AsciiStr;
}
CHAR8 *get_pci_dev_path(pci_dt_t *PciDt)
{
  //	DBG("get_pci_dev_path");
  CHAR8*		tmp;
  CHAR16*		devpathstr = NULL;
  EFI_DEVICE_PATH_PROTOCOL*	DevicePath = NULL;
  
  DevicePath = DevicePathFromHandle (PciDt->DeviceHandle);
  if (!DevicePath)
    return NULL;
  devpathstr = FileDevicePathToStr(DevicePath);
  tmp = AllocateZeroPool((StrLen(devpathstr)+1)*sizeof(CHAR16));
  UnicodeStrToAsciiStr(devpathstr, tmp);
  return tmp;
  
}
Esempio n. 10
0
INTN
EFIAPI
ShellAppMain (
          IN UINTN Argc,
          IN CHAR16 **Argv
              )
{

    char FilenameA[32];
    if(Argc == 2){
        UnicodeStrToAsciiStr(FilenameA, Argv[1]);
        filename = FilenameA;
    }
    else 
        filename = "test.wav";
    UefiMain(gImageHandle, gST);
}
Esempio n. 11
0
EFI_STATUS
EditHIInputAscii (
  IN OUT CHAR8   *CmdLine,
  IN     UINTN   MaxCmdLine
  )
{
  CHAR16*     Str;
  EFI_STATUS  Status;

  Str = (CHAR16*)AllocatePool (MaxCmdLine * sizeof(CHAR16));
  AsciiStrToUnicodeStr (CmdLine, Str);

  Status = EditHIInputStr (Str, MaxCmdLine);
  if (!EFI_ERROR(Status)) {
    UnicodeStrToAsciiStr (Str, CmdLine);
  }
  FreePool (Str);

  return Status;
}
Esempio n. 12
0
// Function to tell the firmware that OS X is being launched. This is
// required to work around problems on some Macs that don't fully
// initialize some hardware (especially video displays) when third-party
// OSes are launched in EFI mode.
EFI_STATUS SetAppleOSInfo() {
    CHAR16 *AppleOSVersion = NULL;
    CHAR8 *AppleOSVersion8 = NULL;
    EFI_STATUS Status;
    EFI_GUID apple_set_os_guid = EFI_APPLE_SET_OS_PROTOCOL_GUID;
    EfiAppleSetOsInterface *SetOs = NULL;

    Status = refit_call3_wrapper(BS->LocateProtocol, &apple_set_os_guid, NULL, (VOID**) &SetOs);

    // If not a Mac, ignore the call....
    if ((Status != EFI_SUCCESS) || (!SetOs))
        return EFI_SUCCESS;

    if ((SetOs->Version != 0) && GlobalConfig.SpoofOSXVersion) {
        AppleOSVersion = StrDuplicate(L"Mac OS X");
        MergeStrings(&AppleOSVersion, GlobalConfig.SpoofOSXVersion, ' ');
        if (AppleOSVersion) {
            AppleOSVersion8 = AllocateZeroPool((StrLen(AppleOSVersion) + 1) * sizeof(CHAR8));
            UnicodeStrToAsciiStr(AppleOSVersion, AppleOSVersion8);
            if (AppleOSVersion8) {
                Status = refit_call1_wrapper (SetOs->SetOsVersion, AppleOSVersion8);
                if (!EFI_ERROR(Status))
                    Status = EFI_SUCCESS;
                MyFreePool(AppleOSVersion8);
            } else {
                Status = EFI_OUT_OF_RESOURCES;
                Print(L"Out of resources in SetAppleOSInfo!\n");
            }
            if ((Status == EFI_SUCCESS) && (SetOs->Version == 2))
                Status = refit_call1_wrapper (SetOs->SetOsVendor, (CHAR8 *) "Apple Inc.");
            MyFreePool(AppleOSVersion);
        } // if (AppleOSVersion)
    } // if
    if (Status != EFI_SUCCESS)
        Print(L"Unable to set firmware boot type!\n");

    return (Status);
} // EFI_STATUS SetAppleOSInfo()
Esempio n. 13
0
/**
  Allows a program to determine which secondary languages are supported on a given handle for a given primary language

  This routine is intended to be used by drivers to query the interface database for supported languages. 
  This routine returns a string of concatenated 3-byte language identifiers, one per string package associated with the handle.

  @param This           A pointer to the EFI_HII_PROTOCOL instance.
  @param Handle         The handle on which the strings reside. Type EFI_HII_HANDLE is defined in EFI_HII_PROTOCOL.NewPack() 
                        in the Packages section.
  @param PrimaryLanguage Pointer to a NULL-terminated string containing a single ISO 639-2 language identifier, indicating 
                         the primary language.
  @param LanguageString  A string allocated by GetSecondaryLanguages() containing a list of all secondary languages registered 
                         on the handle. The routine will not return the three-spaces language identifier used in other functions 
                         to indicate non-language-specific strings, nor will it return the primary language. This function succeeds 
                         but returns a NULL LanguageString if there are no secondary languages associated with the input Handle and 
                         PrimaryLanguage pair. Type EFI_STRING is defined in String.
  
  @retval EFI_SUCCESS            LanguageString was correctly returned.
  @retval EFI_INVALID_PARAMETER  The Handle was unknown.
**/
EFI_STATUS
EFIAPI
HiiGetSecondaryLanguages (
  IN  EFI_HII_PROTOCOL              *This,
  IN  FRAMEWORK_EFI_HII_HANDLE      Handle,
  IN  CHAR16                        *PrimaryLanguage,
  OUT EFI_STRING                    *LanguageString
  )
{
  HII_THUNK_PRIVATE_DATA     *Private;
  EFI_HII_HANDLE             UefiHiiHandle;
  CHAR8                      *PrimaryLang4646;
  CHAR8                      *PrimaryLang639;
  CHAR8                      *SecLangCodes4646;
  CHAR8                      *SecLangCodes639;
  CHAR16                     *UnicodeSecLangCodes639;
  EFI_STATUS                 Status;

  Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);

  SecLangCodes639        = NULL;
  SecLangCodes4646       = NULL;
  PrimaryLang4646        = NULL;
  UnicodeSecLangCodes639 = NULL;

  UefiHiiHandle = FwHiiHandleToUefiHiiHandle (Private, Handle);
  if (UefiHiiHandle == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  PrimaryLang639 = AllocateZeroPool (StrLen (PrimaryLanguage) + 1);
  if (PrimaryLang639 == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Done;
  }

  UnicodeStrToAsciiStr (PrimaryLanguage, PrimaryLang639);

  PrimaryLang4646 = ConvertLanguagesIso639ToRfc4646 (PrimaryLang639);
  ASSERT_EFI_ERROR (PrimaryLang4646 != NULL);

  SecLangCodes4646 = HiiGetSupportedSecondaryLanguages (UefiHiiHandle, PrimaryLang4646);

  if (SecLangCodes4646 == NULL) {
    Status =  EFI_INVALID_PARAMETER;
    goto Done;
  }

  SecLangCodes639 = ConvertLanguagesIso639ToRfc4646 (SecLangCodes4646);
  if (SecLangCodes639 == NULL) {
    Status =  EFI_INVALID_PARAMETER;
    goto Done;
  }

  UnicodeSecLangCodes639 = AllocateZeroPool (AsciiStrSize (SecLangCodes639) * sizeof (CHAR16));
  if (UnicodeSecLangCodes639 == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Done;
  }

  //
  // The language returned is in RFC 4646 format.
  //
  *LanguageString = AsciiStrToUnicodeStr (SecLangCodes639, UnicodeSecLangCodes639);
  Status = EFI_SUCCESS;

Done:
  if (PrimaryLang639 != NULL) {
    FreePool (PrimaryLang639);
  }

  if (SecLangCodes639 != NULL) {
    FreePool (SecLangCodes639);
  }

  if (PrimaryLang4646 != NULL) {
    FreePool (PrimaryLang4646);
  }

  if (SecLangCodes4646 != NULL) {
    FreePool (SecLangCodes4646);
  }
  if (UnicodeSecLangCodes639 != NULL) {
    FreePool (UnicodeSecLangCodes639);
  }
  
  return Status;
}
Esempio n. 14
0
/**
  Opens a file on the Nor Flash FS volume

  Calls BootMonFsGetFileFromAsciiFilename to search the list of tracked files.

  @param  This  The EFI_FILE_PROTOCOL parent handle.
  @param  NewHandle Double-pointer to the newly created protocol.
  @param  FileName The name of the image/metadata on flash
  @param  OpenMode Read,write,append etc
  @param  Attributes ?

  @return EFI_STATUS
  OUT_OF_RESOURCES
    Run out of space to keep track of the allocated structures
  DEVICE_ERROR
    Unable to locate the volume associated with the parent file handle
  NOT_FOUND
    Filename wasn't found on flash
  SUCCESS

**/
EFIAPI
EFI_STATUS
BootMonFsOpenFile (
  IN EFI_FILE_PROTOCOL  *This,
  OUT EFI_FILE_PROTOCOL **NewHandle,
  IN CHAR16             *FileName,
  IN UINT64             OpenMode,
  IN UINT64             Attributes
  )
{
  BOOTMON_FS_FILE     *Directory;
  BOOTMON_FS_FILE     *File;
  BOOTMON_FS_INSTANCE *Instance;
  CHAR8*               AsciiFileName;
  EFI_STATUS           Status;

  if ((FileName == NULL) || (NewHandle == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  // The only valid modes are read, read/write, and read/write/create
  if (!(OpenMode & EFI_FILE_MODE_READ) || ((OpenMode & EFI_FILE_MODE_CREATE)  && !(OpenMode & EFI_FILE_MODE_WRITE))) {
    return EFI_INVALID_PARAMETER;
  }

  Directory = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
  if (Directory == NULL) {
    return EFI_DEVICE_ERROR;
  }

  Instance = Directory->Instance;

  // If the instance has not been initialized it yet then do it ...
  if (!Instance->Initialized) {
    Status = BootMonFsInitialize (Instance);
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }

  // BootMonFs interface requires ASCII filenames
  AsciiFileName = AllocatePool ((StrLen (FileName) + 1) * sizeof (CHAR8));
  if (AsciiFileName == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  UnicodeStrToAsciiStr (FileName, AsciiFileName);

  if ((AsciiStrCmp (AsciiFileName, "\\") == 0) ||
      (AsciiStrCmp (AsciiFileName, "/")  == 0) ||
      (AsciiStrCmp (AsciiFileName, "")   == 0) ||
      (AsciiStrCmp (AsciiFileName, ".")  == 0))
  {
    //
    // Opening '/', '\', '.', or the NULL pathname is trying to open the root directory
    //

    *NewHandle = &Instance->RootFile->File;
    Instance->RootFile->Position = 0;
    Status = EFI_SUCCESS;
  } else {
    //
    // Open or Create a regular file
    //

    // Check if the file already exists
    Status = BootMonGetFileFromAsciiFileName (Instance, AsciiFileName, &File);
    if (Status == EFI_NOT_FOUND) {
      // The file doesn't exist.
      if (OpenMode & EFI_FILE_MODE_CREATE) {
        // If the file does not exist but is required then create it.
        if (Attributes & EFI_FILE_DIRECTORY) {
          // BootMonFS doesn't support subdirectories
          Status = EFI_UNSUPPORTED;
        } else {
          // Create a new file
          Status = CreateNewFile (Instance, AsciiFileName, &File);
          if (!EFI_ERROR (Status)) {
            File->OpenMode = OpenMode;
            *NewHandle = &File->File;
            File->Position = 0;
          }
        }
      }
    } else if (Status == EFI_SUCCESS) {
      // The file exists
      File->OpenMode = OpenMode;
      *NewHandle = &File->File;
      File->Position = 0;
    }
  }

  FreePool (AsciiFileName);

  return Status;
}
Esempio n. 15
0
/**
  Download an image from a TFTP server

  @param[in]   DevicePath           Device path of the TFTP boot option
  @param[in]   ControllerHandle     Handle of the network controller
  @param[in]   RemainingDevicePath  Device path of the TFTP boot option but
                                    the first node that identifies the network controller
  @param[in]   Type                 Type to allocate memory pages
  @param[out]  Image                Address of the bufer where the image is stored in
                                    case of success
  @param[out]  ImageSize            Size in number of bytes of the i;age in case of
                                    success

  @retval  EFI_SUCCESS   The image was returned.
  @retval  !EFI_SUCCESS  Something went wrong.

**/
EFI_STATUS
BdsTftpLoadImage (
  IN OUT EFI_DEVICE_PATH       **DevicePath,
  IN     EFI_HANDLE            ControllerHandle,
  IN     EFI_DEVICE_PATH       *RemainingDevicePath,
  IN     EFI_ALLOCATE_TYPE     Type,
  IN OUT EFI_PHYSICAL_ADDRESS  *Image,
  OUT    UINTN                 *ImageSize
  )
{
  EFI_STATUS               Status;
  EFI_HANDLE               Dhcp4ChildHandle;
  EFI_DHCP4_PROTOCOL       *Dhcp4;
  BOOLEAN                  Dhcp4ToStop;
  EFI_HANDLE               Mtftp4ChildHandle;
  EFI_MTFTP4_PROTOCOL      *Mtftp4;
  DHCP4_OPTION             ParaList;
  EFI_DHCP4_PACKET_OPTION  *OptionList[2];
  EFI_DHCP4_CONFIG_DATA    Dhcp4CfgData;
  EFI_DHCP4_MODE_DATA      Dhcp4Mode;
  EFI_MTFTP4_CONFIG_DATA   Mtftp4CfgData;
  IPv4_DEVICE_PATH         *IPv4DevicePathNode;
  FILEPATH_DEVICE_PATH     *FilePathDevicePathNode;
  CHAR8                    *AsciiFilePath;
  EFI_MTFTP4_TOKEN         Mtftp4Token;
  UINT64                   FileSize;
  UINT64                   TftpBufferSize;
  BDS_TFTP_CONTEXT         *TftpContext;

  ASSERT(IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv4_DP));
  IPv4DevicePathNode = (IPv4_DEVICE_PATH*)RemainingDevicePath;

  Dhcp4ChildHandle  = NULL;
  Dhcp4             = NULL;
  Dhcp4ToStop       = FALSE;
  Mtftp4ChildHandle = NULL;
  Mtftp4            = NULL;
  AsciiFilePath     = NULL;
  TftpContext       = NULL;

  if (!IPv4DevicePathNode->StaticIpAddress) {
    //
    // Using the DHCP4 Service Binding Protocol, create a child handle of the DHCP4 service and
    // install the DHCP4 protocol on it. Then, open the DHCP protocol.
    //
    Status = NetLibCreateServiceChild (
               ControllerHandle,
               gImageHandle,
               &gEfiDhcp4ServiceBindingProtocolGuid,
               &Dhcp4ChildHandle
               );
    if (!EFI_ERROR (Status)) {
      Status = gBS->OpenProtocol (
                      Dhcp4ChildHandle,
                      &gEfiDhcp4ProtocolGuid,
                      (VOID **) &Dhcp4,
                      gImageHandle,
                      ControllerHandle,
                      EFI_OPEN_PROTOCOL_BY_DRIVER
                      );
    }
    if (EFI_ERROR (Status)) {
      Print (L"Unable to open DHCP4 protocol\n");
      goto Error;
    }
  }

  //
  // Using the MTFTP4 Service Binding Protocol, create a child handle of the MTFTP4 service and
  // install the MTFTP4 protocol on it. Then, open the MTFTP4 protocol.
  //
  Status = NetLibCreateServiceChild (
             ControllerHandle,
             gImageHandle,
             &gEfiMtftp4ServiceBindingProtocolGuid,
             &Mtftp4ChildHandle
             );
  if (!EFI_ERROR (Status)) {
    Status = gBS->OpenProtocol (
                    Mtftp4ChildHandle,
                    &gEfiMtftp4ProtocolGuid,
                    (VOID **) &Mtftp4,
                    gImageHandle,
                    ControllerHandle,
                    EFI_OPEN_PROTOCOL_BY_DRIVER
                    );
  }
  if (EFI_ERROR (Status)) {
    Print (L"Unable to open MTFTP4 protocol\n");
    goto Error;
  }

  if (!IPv4DevicePathNode->StaticIpAddress) {
    //
    // Configure the DHCP4, all default settings. It is acceptable for the configuration to
    // fail if the return code is equal to EFI_ACCESS_DENIED which means that the configuration
    // has been done by another instance of the DHCP4 protocol or that the DHCP configuration
    // process has been started but is not completed yet.
    //
    ZeroMem (&Dhcp4CfgData, sizeof (EFI_DHCP4_CONFIG_DATA));
    ParaList.Head.OpCode     = DHCP_TAG_PARA_LIST;
    ParaList.Head.Length     = 2;
    ParaList.Head.Data[0]    = DHCP_TAG_NETMASK;
    ParaList.Route           = DHCP_TAG_ROUTER;
    OptionList[0]            = &ParaList.Head;
    Dhcp4CfgData.OptionCount = 1;
    Dhcp4CfgData.OptionList  = OptionList;

    Status = Dhcp4->Configure (Dhcp4, &Dhcp4CfgData);
    if (EFI_ERROR (Status)) {
      if (Status != EFI_ACCESS_DENIED) {
        Print (L"Error while configuring the DHCP4 protocol\n");
        goto Error;
      }
    }

    //
    // Start the DHCP configuration. This may have already been done thus do not leave in error
    // if the return code is EFI_ALREADY_STARTED.
    //
    Status = Dhcp4->Start (Dhcp4, NULL);
    if (EFI_ERROR (Status)) {
      if (Status != EFI_ALREADY_STARTED) {
        Print (L"DHCP configuration failed\n");
        goto Error;
      }
    } else {
      Dhcp4ToStop = TRUE;
    }

    Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);
    if (EFI_ERROR (Status)) {
      goto Error;
    }

    if (Dhcp4Mode.State != Dhcp4Bound) {
      Status = EFI_TIMEOUT;
      Print (L"DHCP configuration failed\n");
      goto Error;
    }
  }

  //
  // Configure the TFTP4 protocol
  //

  ZeroMem (&Mtftp4CfgData, sizeof (EFI_MTFTP4_CONFIG_DATA));
  Mtftp4CfgData.UseDefaultSetting = FALSE;
  Mtftp4CfgData.TimeoutValue      = 4;
  Mtftp4CfgData.TryCount          = 6;

  if (IPv4DevicePathNode->StaticIpAddress) {
    CopyMem (&Mtftp4CfgData.StationIp , &IPv4DevicePathNode->LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&Mtftp4CfgData.SubnetMask, &IPv4DevicePathNode->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&Mtftp4CfgData.GatewayIp , &IPv4DevicePathNode->GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS));
  } else {
    CopyMem (&Mtftp4CfgData.StationIp , &Dhcp4Mode.ClientAddress, sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&Mtftp4CfgData.SubnetMask, &Dhcp4Mode.SubnetMask   , sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&Mtftp4CfgData.GatewayIp , &Dhcp4Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS));
  }

  CopyMem (&Mtftp4CfgData.ServerIp  , &IPv4DevicePathNode->RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS));

  Status = Mtftp4->Configure (Mtftp4, &Mtftp4CfgData);
  if (EFI_ERROR (Status)) {
    Print (L"Error while configuring the MTFTP4 protocol\n");
    goto Error;
  }

  //
  // Convert the Unicode path of the file to Ascii
  //

  FilePathDevicePathNode = (FILEPATH_DEVICE_PATH*)(IPv4DevicePathNode + 1);
  AsciiFilePath = AllocatePool ((StrLen (FilePathDevicePathNode->PathName) + 1) * sizeof (CHAR8));
  if (AsciiFilePath == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Error;
  }
  UnicodeStrToAsciiStr (FilePathDevicePathNode->PathName, AsciiFilePath);

  //
  // Try to get the size of the file in bytes from the server. If it fails,
  // start with a 8MB buffer to download the file.
  //
  FileSize = 0;
  if (Mtftp4GetFileSize (Mtftp4, AsciiFilePath, &FileSize) == EFI_SUCCESS) {
    TftpBufferSize = FileSize;
  } else {
    TftpBufferSize = SIZE_8MB;
  }

  TftpContext = AllocatePool (sizeof (BDS_TFTP_CONTEXT));
  if (TftpContext == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Error;
  }
  TftpContext->FileSize = FileSize;

  for (; TftpBufferSize <= FixedPcdGet32 (PcdMaxTftpFileSize);
         TftpBufferSize = (TftpBufferSize + SIZE_8MB) & (~(SIZE_8MB-1))) {
    //
    // Allocate a buffer to hold the whole file.
    //
    Status = gBS->AllocatePages (
                    Type,
                    EfiBootServicesCode,
                    EFI_SIZE_TO_PAGES (TftpBufferSize),
                    Image
                    );
    if (EFI_ERROR (Status)) {
      Print (L"Failed to allocate space for image\n");
      goto Error;
    }

    TftpContext->DownloadedNbOfBytes   = 0;
    TftpContext->LastReportedNbOfBytes = 0;

    ZeroMem (&Mtftp4Token, sizeof (EFI_MTFTP4_TOKEN));
    Mtftp4Token.Filename    = (UINT8*)AsciiFilePath;
    Mtftp4Token.BufferSize  = TftpBufferSize;
    Mtftp4Token.Buffer      = (VOID *)(UINTN)*Image;
    Mtftp4Token.CheckPacket = Mtftp4CheckPacket;
    Mtftp4Token.Context     = (VOID*)TftpContext;

    Print (L"Downloading the file <%s> from the TFTP server\n", FilePathDevicePathNode->PathName);
    Status = Mtftp4->ReadFile (Mtftp4, &Mtftp4Token);
    Print (L"\n");
    if (EFI_ERROR (Status)) {
      gBS->FreePages (*Image, EFI_SIZE_TO_PAGES (TftpBufferSize));
      if (Status == EFI_BUFFER_TOO_SMALL) {
        Print (L"Downloading failed, file larger than expected.\n");
        continue;
      } else {
        goto Error;
      }
    }

    *ImageSize = Mtftp4Token.BufferSize;
    break;
  }

Error:
  if (Dhcp4ChildHandle != NULL) {
    if (Dhcp4 != NULL) {
      if (Dhcp4ToStop) {
        Dhcp4->Stop (Dhcp4);
      }
      gBS->CloseProtocol (
             Dhcp4ChildHandle,
             &gEfiDhcp4ProtocolGuid,
             gImageHandle,
             ControllerHandle
            );
    }
    NetLibDestroyServiceChild (
      ControllerHandle,
      gImageHandle,
      &gEfiDhcp4ServiceBindingProtocolGuid,
      Dhcp4ChildHandle
      );
  }

  if (Mtftp4ChildHandle != NULL) {
    if (Mtftp4 != NULL) {
      if (AsciiFilePath != NULL) {
        FreePool (AsciiFilePath);
      }
      if (TftpContext != NULL) {
        FreePool (TftpContext);
      }
      gBS->CloseProtocol (
             Mtftp4ChildHandle,
             &gEfiMtftp4ProtocolGuid,
             gImageHandle,
             ControllerHandle
            );
    }
    NetLibDestroyServiceChild (
      ControllerHandle,
      gImageHandle,
      &gEfiMtftp4ServiceBindingProtocolGuid,
      Mtftp4ChildHandle
      );
  }

  if (EFI_ERROR (Status)) {
    Print (L"Failed to download the file - Error=%r\n", Status);
  }

  return Status;
}
Esempio n. 16
0
File: Tftp.c Progetto: rsalveti/edk2
/**
  Function for 'tftp' command.

  @param[in] ImageHandle  Handle to the Image (NULL if Internal).
  @param[in] SystemTable  Pointer to the System Table (NULL if Internal).

  @return  SHELL_SUCCESS            The 'tftp' command completed successfully.
  @return  SHELL_ABORTED            The Shell Library initialization failed.
  @return  SHELL_INVALID_PARAMETER  At least one of the command's arguments is
                                    not valid.
  @return  SHELL_OUT_OF_RESOURCES   A memory allocation failed.
  @return  SHELL_NOT_FOUND          Network Interface Card not found or server
                                    error or file error.

**/
SHELL_STATUS
EFIAPI
ShellCommandRunTftp (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  SHELL_STATUS            ShellStatus;
  EFI_STATUS              Status;
  LIST_ENTRY              *CheckPackage;
  CHAR16                  *ProblemParam;
  UINTN                   ParamCount;
  CONST CHAR16            *UserNicName;
  BOOLEAN                 NicFound;
  CONST CHAR16            *ValueStr;
  CONST CHAR16            *RemoteFilePath;
  CHAR8                   *AsciiRemoteFilePath;
  CONST CHAR16            *Walker;
  CONST CHAR16            *LocalFilePath;
  EFI_MTFTP4_CONFIG_DATA  Mtftp4ConfigData;
  EFI_HANDLE              *Handles;
  UINTN                   HandleCount;
  UINTN                   NicNumber;
  CHAR16                  NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH];
  EFI_HANDLE              ControllerHandle;
  EFI_HANDLE              Mtftp4ChildHandle;
  EFI_MTFTP4_PROTOCOL     *Mtftp4;
  UINTN                   FileSize;
  VOID                    *Data;
  SHELL_FILE_HANDLE       FileHandle;

  ShellStatus         = SHELL_INVALID_PARAMETER;
  ProblemParam        = NULL;
  NicFound            = FALSE;
  AsciiRemoteFilePath = NULL;
  Handles             = NULL;
  FileSize            = 0;

  //
  // Initialize the Shell library (we must be in non-auto-init...)
  //
  Status = ShellInitialize ();
  if (EFI_ERROR (Status)) {
    ASSERT_EFI_ERROR (Status);
    return SHELL_ABORTED;
  }

  //
  // Parse the command line.
  //
  Status = ShellCommandLineParse (ParamList, &CheckPackage, &ProblemParam, TRUE);
  if (EFI_ERROR (Status)) {
    if ((Status == EFI_VOLUME_CORRUPTED) &&
        (ProblemParam != NULL) ) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellTftpHiiHandle,
        L"tftp", ProblemParam
        );
      FreePool (ProblemParam);
    } else {
      ASSERT (FALSE);
    }
    goto Error;
  }

  //
  // Check the number of parameters
  //
  ParamCount = ShellCommandLineGetCount (CheckPackage);
  if (ParamCount > 4) {
    ShellPrintHiiEx (
      -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY),
      gShellTftpHiiHandle, L"tftp"
      );
    goto Error;
  }
  if (ParamCount < 3) {
    ShellPrintHiiEx (
      -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW),
      gShellTftpHiiHandle, L"tftp"
      );
    goto Error;
  }

  Mtftp4ConfigData = DefaultMtftp4ConfigData;

  //
  // Check the host IPv4 address
  //
  ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1);
  Status = NetLibStrToIp4 (ValueStr, &Mtftp4ConfigData.ServerIp);
  if (EFI_ERROR (Status)) {
    ShellPrintHiiEx (
      -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
      gShellTftpHiiHandle, L"tftp", ValueStr
    );
    goto Error;
  }

  RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2);
  AsciiRemoteFilePath = AllocatePool (
                          (StrLen (RemoteFilePath) + 1) * sizeof (CHAR8)
                          );
  if (AsciiRemoteFilePath == NULL) {
    ShellStatus = SHELL_OUT_OF_RESOURCES;
    goto Error;
  }
  UnicodeStrToAsciiStr (RemoteFilePath, AsciiRemoteFilePath);

  if (ParamCount == 4) {
    LocalFilePath = ShellCommandLineGetRawValue (CheckPackage, 3);
  } else {
    Walker = RemoteFilePath + StrLen (RemoteFilePath);
    while ((--Walker) >= RemoteFilePath) {
      if ((*Walker == L'\\') ||
          (*Walker == L'/' )    ) {
        break;
      }
    }
    LocalFilePath = Walker + 1;
  }

  //
  // Get the name of the Network Interface Card to be used if any.
  //
  UserNicName = ShellCommandLineGetValue (CheckPackage, L"-i");

  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-l");
  if (ValueStr != NULL) {
    if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.LocalPort)) {
      goto Error;
    }
  }

  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-r");
  if (ValueStr != NULL) {
    if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.InitialServerPort)) {
      goto Error;
    }
  }

  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-c");
  if (ValueStr != NULL) {
    if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TryCount)) {
      goto Error;
    }
  }

  ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t");
  if (ValueStr != NULL) {
    if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TimeoutValue)) {
      goto Error;
    }
    if (Mtftp4ConfigData.TimeoutValue == 0) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
        gShellTftpHiiHandle, L"tftp", ValueStr
      );
      goto Error;
    }
  }

  //
  // Locate all MTFTP4 Service Binding protocols
  //
  ShellStatus = SHELL_NOT_FOUND;
  Status = gBS->LocateHandleBuffer (
                 ByProtocol,
                 &gEfiManagedNetworkServiceBindingProtocolGuid,
                 NULL,
                 &HandleCount,
                 &Handles
                 );
  if (EFI_ERROR (Status) || (HandleCount == 0)) {
    ShellPrintHiiEx (
      -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NO_NIC),
      gShellTftpHiiHandle
    );
    goto Error;
  }

  for (NicNumber = 0;
       (NicNumber < HandleCount) && (ShellStatus != SHELL_SUCCESS);
       NicNumber++) {
    ControllerHandle = Handles[NicNumber];
    Data = NULL;

    Status = GetNicName (ControllerHandle, NicNumber, NicName);
    if (EFI_ERROR (Status)) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NAME),
        gShellTftpHiiHandle, NicNumber, Status
      );
      continue;
    }

    if (UserNicName != NULL) {
      if (StrCmp (NicName, UserNicName) != 0) {
        continue;
      }
      NicFound = TRUE;
    }

    Status = CreateServiceChildAndOpenProtocol (
               ControllerHandle,
               &gEfiMtftp4ServiceBindingProtocolGuid,
               &gEfiMtftp4ProtocolGuid,
               &Mtftp4ChildHandle,
               (VOID**)&Mtftp4
               );
    if (EFI_ERROR (Status)) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_OPEN_PROTOCOL),
        gShellTftpHiiHandle, NicName, Status
      );
      continue;
    }

    Status = Mtftp4->Configure (Mtftp4, &Mtftp4ConfigData);
    if (EFI_ERROR (Status)) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_CONFIGURE),
        gShellTftpHiiHandle, NicName, Status
      );
      goto NextHandle;
    }

    Status = GetFileSize (Mtftp4, AsciiRemoteFilePath, &FileSize);
    if (EFI_ERROR (Status)) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_FILE_SIZE),
        gShellTftpHiiHandle, RemoteFilePath, NicName, Status
      );
      goto NextHandle;
    }

    Status = DownloadFile (Mtftp4, RemoteFilePath, AsciiRemoteFilePath, FileSize, &Data);
    if (EFI_ERROR (Status)) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_DOWNLOAD),
        gShellTftpHiiHandle, RemoteFilePath, NicName, Status
      );
      goto NextHandle;
    }

    if (!EFI_ERROR (ShellFileExists (LocalFilePath))) {
      ShellDeleteFileByName (LocalFilePath);
    }

    Status = ShellOpenFileByName (
               LocalFilePath,
               &FileHandle,
               EFI_FILE_MODE_CREATE |
               EFI_FILE_MODE_WRITE  |
               EFI_FILE_MODE_READ,
               0
               );
    if (EFI_ERROR (Status)) {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL),
        gShellTftpHiiHandle, L"tftp", LocalFilePath
      );
      goto NextHandle;
    }

    Status = ShellWriteFile (FileHandle, &FileSize, Data);
    if (!EFI_ERROR (Status)) {
      ShellStatus = SHELL_SUCCESS;
    } else {
      ShellPrintHiiEx (
        -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_WRITE),
        gShellTftpHiiHandle, LocalFilePath, Status
      );
    }
    ShellCloseFile (&FileHandle);

    NextHandle:

    if (Data != NULL) {
      gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Data, EFI_SIZE_TO_PAGES (FileSize));
    }

    CloseProtocolAndDestroyServiceChild (
      ControllerHandle,
      &gEfiMtftp4ServiceBindingProtocolGuid,
      &gEfiMtftp4ProtocolGuid,
      Mtftp4ChildHandle
      );
  }

  if ((UserNicName != NULL) && (!NicFound)) {
    ShellPrintHiiEx (
      -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NOT_FOUND),
      gShellTftpHiiHandle, UserNicName
    );
  }

  Error:

  ShellCommandLineFreeVarList (CheckPackage);
  if (AsciiRemoteFilePath != NULL) {
    FreePool (AsciiRemoteFilePath);
  }
  if (Handles != NULL) {
    FreePool (Handles);
  }

  return ShellStatus;
}
Esempio n. 17
0
/**
  Add new boot option for HTTP boot.

  @param[in]  Private             Pointer to the driver private data.
  @param[in]  UsingIpv6           Set to TRUE if creating boot option for IPv6.
  @param[in]  Description         The description text of the boot option.
  @param[in]  Uri                 The URI string of the boot file.
  
  @retval EFI_SUCCESS             The boot option is created successfully.
  @retval Others                  Failed to create new boot option.

**/
EFI_STATUS
HttpBootAddBootOption (
  IN   HTTP_BOOT_PRIVATE_DATA   *Private,
  IN   BOOLEAN                  UsingIpv6,
  IN   CHAR16                   *Description,
  IN   CHAR16                   *Uri
  )
{
  EFI_DEV_PATH               *Node;
  EFI_DEVICE_PATH_PROTOCOL   *TmpDevicePath;
  EFI_DEVICE_PATH_PROTOCOL   *NewDevicePath;
  UINTN                      Length;
  CHAR8                      AsciiUri[URI_STR_MAX_SIZE];
  CHAR16                     *CurrentOrder;
  EFI_STATUS                 Status;
  UINTN                      OrderCount;
  UINTN                      TargetLocation;
  BOOLEAN                    Found;
  UINT8                      *TempByteBuffer;
  UINT8                      *TempByteStart;
  UINTN                      DescSize;
  UINTN                      FilePathSize;
  CHAR16                     OptionStr[10];
  UINT16                     *NewOrder;
  UINTN                      Index;

  NewOrder      = NULL;
  TempByteStart = NULL;
  NewDevicePath = NULL;
  NewOrder      = NULL;
  Node          = NULL;
  TmpDevicePath = NULL;
  CurrentOrder  = NULL;

  if (StrLen (Description) == 0) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Convert the scheme to all lower case.
  //
  for (Index = 0; Index < StrLen (Uri); Index++) {
    if (Uri[Index] == L':') {
      break;
    }
    if (Uri[Index] >= L'A' && Uri[Index] <= L'Z') {
      Uri[Index] -= (CHAR16)(L'A' - L'a');
    }
  }

  //
  // Only accept http and https URI.
  //
  if ((StrnCmp (Uri, L"http://", 7) != 0) && (StrnCmp (Uri, L"https://", 7) != 0)) {
    return EFI_INVALID_PARAMETER;
  }
  
  //
  // Create a new device path by appending the IP node and URI node to
  // the driver's parent device path
  //
  if (!UsingIpv6) {
    Node = AllocateZeroPool (sizeof (IPv4_DEVICE_PATH));
    if (Node == NULL) {
      Status = EFI_OUT_OF_RESOURCES;
      goto ON_EXIT;
    }
    Node->Ipv4.Header.Type    = MESSAGING_DEVICE_PATH;
    Node->Ipv4.Header.SubType = MSG_IPv4_DP;
    SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH));
  } else {
    Node = AllocateZeroPool (sizeof (IPv6_DEVICE_PATH));
    if (Node == NULL) {
      Status = EFI_OUT_OF_RESOURCES;
      goto ON_EXIT;
    }
    Node->Ipv6.Header.Type     = MESSAGING_DEVICE_PATH;
    Node->Ipv6.Header.SubType  = MSG_IPv6_DP;
    SetDevicePathNodeLength (Node, sizeof (IPv6_DEVICE_PATH));
  }
  TmpDevicePath = AppendDevicePathNode (Private->ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);
  FreePool (Node);
  if (TmpDevicePath == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // Update the URI node with the input boot file URI.
  //
  UnicodeStrToAsciiStr (Uri, AsciiUri);
  Length = sizeof (EFI_DEVICE_PATH_PROTOCOL) + AsciiStrSize (AsciiUri);
  Node = AllocatePool (Length);
  if (Node == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    FreePool (TmpDevicePath);
    goto ON_EXIT;
  }
  Node->DevPath.Type    = MESSAGING_DEVICE_PATH;
  Node->DevPath.SubType = MSG_URI_DP;
  SetDevicePathNodeLength (Node, Length);
  CopyMem ((UINT8*) Node + sizeof (EFI_DEVICE_PATH_PROTOCOL), AsciiUri, AsciiStrSize (AsciiUri));
  NewDevicePath = AppendDevicePathNode (TmpDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);
  FreePool (Node);
  FreePool (TmpDevicePath);
  if (NewDevicePath == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_EXIT;
  }

  //
  // Get current "BootOrder" variable and find a free target.
  //
  Length = 0;
  Status = GetVariable2 (
             L"BootOrder",
             &gEfiGlobalVariableGuid,
             (VOID **)&CurrentOrder,
             &Length 
             );
  if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
    goto ON_EXIT;
  }
  OrderCount = Length / sizeof (UINT16);
  Found = FALSE;
  for (TargetLocation=0; TargetLocation < 0xFFFF; TargetLocation++) {
    Found = TRUE;
    for (Index = 0; Index < OrderCount; Index++) {
      if (CurrentOrder[Index] == TargetLocation) {
        Found = FALSE;
        break;
      }
    }
    if (Found) {
      break;
    }
  }

  if (TargetLocation == 0xFFFF) {
    DEBUG ((EFI_D_ERROR, "Could not find unused target index.\n"));
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_EXIT;
  } else {
    DEBUG ((EFI_D_INFO, "TargetIndex = %04x.\n", TargetLocation));
  }
  
  //
  // Construct and set the "Boot####" variable
  //
  DescSize = StrSize(Description);
  FilePathSize = GetDevicePathSize (NewDevicePath);
  TempByteBuffer = AllocateZeroPool(sizeof(EFI_LOAD_OPTION) + DescSize + FilePathSize);
  if (TempByteBuffer == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_EXIT;
  }

  TempByteStart = TempByteBuffer;
  *((UINT32 *) TempByteBuffer) = LOAD_OPTION_ACTIVE;      // Attributes
  TempByteBuffer += sizeof (UINT32);

  *((UINT16 *) TempByteBuffer) = (UINT16)FilePathSize;    // FilePathListLength
  TempByteBuffer += sizeof (UINT16);

  CopyMem (TempByteBuffer, Description, DescSize);
  TempByteBuffer += DescSize;
  CopyMem (TempByteBuffer, NewDevicePath, FilePathSize);

  UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", L"Boot", TargetLocation);
  Status = gRT->SetVariable (
                  OptionStr,
                  &gEfiGlobalVariableGuid,
                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                  sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize,
                  TempByteStart
                  );
  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }

  //
  // Insert into the order list and set "BootOrder" variable
  //
  NewOrder = AllocateZeroPool ((OrderCount + 1) * sizeof (UINT16));
  if (NewOrder == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_EXIT;
  }
  CopyMem(NewOrder, CurrentOrder, OrderCount * sizeof(UINT16));
  NewOrder[OrderCount] = (UINT16) TargetLocation;
  Status = gRT->SetVariable (
                  L"BootOrder",
                  &gEfiGlobalVariableGuid,
                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                  ((OrderCount + 1) * sizeof (UINT16)),
                  NewOrder
                  );
  

ON_EXIT:

  if (CurrentOrder != NULL) {
    FreePool (CurrentOrder);
  }
  if (NewOrder != NULL) {
    FreePool (NewOrder);
  }
  if (TempByteStart != NULL) {
    FreePool (TempByteStart);
  }
  if (NewDevicePath != NULL) {
    FreePool (NewDevicePath);
  }

  return Status;
}
Esempio n. 18
0
/**
  Set information about a file.

  @param[in]  Fcb   A pointer to the description of the open file.
  @param[in]  Info  A pointer to the file information to write.

  @retval  EFI_SUCCESS           The information was set.
  @retval  EFI_ACCESS_DENIED     An attempt is made to change the name of a file
                                 to a file that is already present.
  @retval  EFI_ACCESS_DENIED     An attempt is being made to change the
                                 EFI_FILE_DIRECTORY Attribute.
  @retval  EFI_ACCESS_DENIED     The file is a read-only file or has been
                                 opened in read-only mode and an attempt is
                                 being made to modify a field other than
                                 Attribute.
  @retval  EFI_WRITE_PROTECTED   An attempt is being made to modify a
                                 read-only attribute.
  @retval  EFI_DEVICE_ERROR      The last issued semi-hosting operation failed.
  @retval  EFI_OUT_OF_RESOURCES  A allocation needed to process the request failed.

**/
STATIC
EFI_STATUS
SetFileInfo (
  IN  SEMIHOST_FCB   *Fcb,
  IN  EFI_FILE_INFO  *Info
  )
{
  EFI_STATUS     Status;
  RETURN_STATUS  Return;
  BOOLEAN        FileSizeIsDifferent;
  BOOLEAN        FileNameIsDifferent;
  BOOLEAN        ReadOnlyIsDifferent;
  CHAR8          *AsciiFileName;
  UINTN          FileSize;
  UINTN          Length;
  UINTN          SemihostHandle;

  //
  // A directory can not be changed to a file and a file can
  // not be changed to a directory.
  //
  if (((Info->Attribute & EFI_FILE_DIRECTORY) != 0) != Fcb->IsRoot) {
    return EFI_ACCESS_DENIED;
  }

  AsciiFileName = AllocatePool (StrLen (Info->FileName) + 1);
  if (AsciiFileName == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  UnicodeStrToAsciiStr (Info->FileName, AsciiFileName);

  FileSizeIsDifferent = (Info->FileSize != Fcb->Info.FileSize);
  FileNameIsDifferent = (AsciiStrCmp (AsciiFileName, Fcb->FileName) != 0);
  ReadOnlyIsDifferent = CompareMem (
                          &Info->CreateTime,
                          &Fcb->Info.CreateTime,
                          3 * sizeof (EFI_TIME)
                          ) != 0;

  //
  // For a read-only file or a file opened in read-only mode, only
  // the Attribute field can be modified. As the root directory is
  // read-only (i.e. VolumeOpen()), this protects the root directory
  // description.
  //
  if ((Fcb->OpenMode == EFI_FILE_MODE_READ)     ||
      (Fcb->Info.Attribute & EFI_FILE_READ_ONLY)  ) {
    if (FileSizeIsDifferent || FileNameIsDifferent || ReadOnlyIsDifferent) {
      Status = EFI_ACCESS_DENIED;
      goto Error;
    }
  }

  if (ReadOnlyIsDifferent) {
    Status = EFI_WRITE_PROTECTED;
    goto Error;
  }

  Status = EFI_DEVICE_ERROR;

  if (FileSizeIsDifferent) {
    FileSize = Info->FileSize;
    if (Fcb->Info.FileSize < FileSize) {
      Status = ExtendFile (Fcb, FileSize - Fcb->Info.FileSize);
      if (EFI_ERROR (Status)) {
        goto Error;
      }
      //
      // The read/write position from the host file system point of view
      // is at the end of the file. If the position from this module
      // point of view is smaller than the new file size, then
      // ask the host file system to move to that position.
      //
      if (Fcb->Position < FileSize) {
        FileSetPosition (&Fcb->File, Fcb->Position);
      }
    }
    Fcb->Info.FileSize = FileSize;

    Return = SemihostFileLength (Fcb->SemihostHandle, &Length);
    if (RETURN_ERROR (Return)) {
      goto Error;
    }
    Fcb->Info.PhysicalSize = Length;
  }

  //
  // Note down in RAM the Attribute field but we can not ask
  // for its modification to the host file system as the
  // semi-host interface does not provide this feature.
  //
  Fcb->Info.Attribute = Info->Attribute;

  if (FileNameIsDifferent) {
    Return = SemihostFileOpen (
               AsciiFileName,
               SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY,
               &SemihostHandle
               );
    if (!RETURN_ERROR (Return)) {
      SemihostFileClose (SemihostHandle);
      Status = EFI_ACCESS_DENIED;
      goto Error;
    }

    Return = SemihostFileRename (Fcb->FileName, AsciiFileName);
    if (RETURN_ERROR (Return)) {
      goto Error;
    }
    FreePool (Fcb->FileName);
    Fcb->FileName = AsciiFileName;
    AsciiFileName = NULL;
  }

  Status = EFI_SUCCESS;

Error:
  if (AsciiFileName != NULL) {
    FreePool (AsciiFileName);
  }

  return Status;
}
Esempio n. 19
0
EFI_STATUS
DefineDefaultBootEntries (
  VOID
  )
{
  BDS_LOAD_OPTION*                    BdsLoadOption;
  UINTN                               Size;
  EFI_STATUS                          Status;
  EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol;
  EFI_DEVICE_PATH*                    BootDevicePath;
  UINTN                               CmdLineSize;
  UINTN                               CmdLineAsciiSize;
  CHAR16*                             DefaultBootArgument;
  CHAR8*                              AsciiDefaultBootArgument;

  //
  // If Boot Order does not exist then create a default entry
  //
  Size = 0;
  Status = gRT->GetVariable (L"BootOrder", &gEfiGlobalVariableGuid, NULL, &Size, NULL);
  if (Status == EFI_NOT_FOUND) {
    if ((PcdGetPtr(PcdDefaultBootDevicePath) == NULL) || (StrLen ((CHAR16*)PcdGetPtr(PcdDefaultBootDevicePath)) == 0)) {
      return EFI_UNSUPPORTED;
    }

    Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
    if (EFI_ERROR(Status)) {
      // You must provide an implementation of DevicePathFromTextProtocol in your firmware (eg: DevicePathDxe)
      DEBUG((EFI_D_ERROR,"Error: Bds requires DevicePathFromTextProtocol\n"));
      return Status;
    }
    BootDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultBootDevicePath));

    DEBUG_CODE_BEGIN();
      // We convert back to the text representation of the device Path to see if the initial text is correct
      EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;
      CHAR16* DevicePathTxt;

      Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);
      ASSERT_EFI_ERROR(Status);
      DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (BootDevicePath, TRUE, TRUE);

      if (StrCmp ((CHAR16*)PcdGetPtr (PcdDefaultBootDevicePath), DevicePathTxt) != 0) {
        DEBUG ((EFI_D_ERROR, "Device Path given: '%s' Device Path expected: '%s'\n",
            (CHAR16*)PcdGetPtr (PcdDefaultBootDevicePath), DevicePathTxt));
        ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
      }

      FreePool (DevicePathTxt);
    DEBUG_CODE_END();

    // Create the entry is the Default values are correct
    if (BootDevicePath != NULL) {
      // We do not support NULL pointer
      ASSERT (PcdGetPtr (PcdDefaultBootArgument) != NULL);

      //
      // Logic to handle ASCII or Unicode default parameters
      //
      if (*(CHAR8*)PcdGetPtr (PcdDefaultBootArgument) == '\0') {
        CmdLineSize = 0;
        CmdLineAsciiSize = 0;
        DefaultBootArgument = NULL;
        AsciiDefaultBootArgument = NULL;
      } else if (IsUnicodeString ((CHAR16*)PcdGetPtr (PcdDefaultBootArgument))) {
        // The command line is a Unicode string
        DefaultBootArgument = (CHAR16*)PcdGetPtr (PcdDefaultBootArgument);
        CmdLineSize = StrSize (DefaultBootArgument);

        // Initialize ASCII variables
        CmdLineAsciiSize = CmdLineSize / 2;
        AsciiDefaultBootArgument = AllocatePool (CmdLineAsciiSize);
        if (AsciiDefaultBootArgument == NULL) {
          return EFI_OUT_OF_RESOURCES;
        }
        UnicodeStrToAsciiStr ((CHAR16*)PcdGetPtr (PcdDefaultBootArgument), AsciiDefaultBootArgument);
      } else {
        // The command line is a ASCII string
        AsciiDefaultBootArgument = (CHAR8*)PcdGetPtr (PcdDefaultBootArgument);
        CmdLineAsciiSize = AsciiStrSize (AsciiDefaultBootArgument);

        // Initialize ASCII variables
        CmdLineSize = CmdLineAsciiSize * 2;
        DefaultBootArgument = AllocatePool (CmdLineSize);
        if (DefaultBootArgument == NULL) {
          return EFI_OUT_OF_RESOURCES;
        }
        AsciiStrToUnicodeStr (AsciiDefaultBootArgument, DefaultBootArgument);
      }

      BootOptionCreate (LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT,
        (CHAR16*)PcdGetPtr (PcdDefaultBootDescription),
        BootDevicePath,
        (UINT8 *)DefaultBootArgument, // OptionalData
        CmdLineSize,                  // OptionalDataSize
        &BdsLoadOption
        );
      FreePool (BdsLoadOption);

      if (DefaultBootArgument == (CHAR16*)PcdGetPtr (PcdDefaultBootArgument)) {
        FreePool (AsciiDefaultBootArgument);
      } else if (DefaultBootArgument != NULL) {
        FreePool (DefaultBootArgument);
      }
    } else {
      Status = EFI_UNSUPPORTED;
    }
  }

  return Status;
}
Esempio n. 20
0
/**
  Create or update a String Token in a String Package.

  If *Reference == 0, a new String Token is created.

  @param This            A pointer to the EFI_HII_PROTOCOL instance.
  @param Language        Pointer to a NULL-terminated string containing a single ISO 639-2 language
                         identifier, indicating the language to print. A string consisting of
                         all spaces indicates that the string is applicable to all languages.
  @param Handle          The handle of the language pack to which the string is to be added.
  @param Reference       The string token assigned to the string.
  @param NewString       The string to be added.


  @retval EFI_SUCCESS             The string was effectively registered.
  @retval EFI_INVALID_PARAMETER   The Handle was unknown. The string is not created or updated in the
                                  the string package.
**/
EFI_STATUS
EFIAPI
HiiNewString (
  IN     EFI_HII_PROTOCOL           *This,
  IN     CHAR16                     *Language,
  IN     FRAMEWORK_EFI_HII_HANDLE   Handle,
  IN OUT STRING_REF                 *Reference,
  IN     CHAR16                     *NewString
  )
{
  EFI_STATUS                                Status;
  HII_THUNK_PRIVATE_DATA                    *Private;
  EFI_GUID                                  TagGuid;
  LIST_ENTRY                                *Link;
  HII_THUNK_CONTEXT                          *ThunkContext;
  HII_THUNK_CONTEXT                          *StringPackThunkContext;
  EFI_STRING_ID                             StringId;
  EFI_STRING_ID                             LastStringId;
  CHAR8                                     AsciiLanguage[ISO_639_2_ENTRY_SIZE + 1];
  CHAR16                                    LanguageCopy[ISO_639_2_ENTRY_SIZE + 1];
  CHAR8                                     *Rfc4646AsciiLanguage;

  LastStringId      = (EFI_STRING_ID) 0;
  StringId          = (EFI_STRING_ID) 0;
  Rfc4646AsciiLanguage = NULL;

  if (Language != NULL) {
    ZeroMem (AsciiLanguage, sizeof (AsciiLanguage));;
    ZeroMem (LanguageCopy, sizeof (LanguageCopy));
    CopyMem (LanguageCopy, Language, ISO_639_2_ENTRY_SIZE * sizeof (CHAR16));
    UnicodeStrToAsciiStr (LanguageCopy, AsciiLanguage);
    Rfc4646AsciiLanguage = ConvertLanguagesIso639ToRfc4646 (AsciiLanguage);
    ASSERT (Rfc4646AsciiLanguage != NULL);
  }

  Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);

  StringPackThunkContext = FwHiiHandleToThunkContext (Private, Handle);
  if (StringPackThunkContext == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  if (StringPackThunkContext->SharingStringPack) {
    Status = GetTagGuidByFwHiiHandle (Private, Handle, &TagGuid);
    ASSERT_EFI_ERROR (Status);

    Link = GetFirstNode (&Private->ThunkContextListHead);
    while (!IsNull (&Private->ThunkContextListHead, Link)) {
      ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);

      if (CompareGuid (&TagGuid, &ThunkContext->TagGuid)) {
        if (ThunkContext->SharingStringPack) {
          StringId = *Reference;
          Status = UpdateString (ThunkContext, Rfc4646AsciiLanguage, NewString, &StringId);
          if (EFI_ERROR (Status)) {
            break;
          }
          
          DEBUG_CODE_BEGIN ();
          if (*Reference == 0) {
            //
            // When creating new string token, make sure all created token is the same
            // for all string packages registered using FW HII interface.
            //
            if (LastStringId == (EFI_STRING_ID) 0) {
              LastStringId = StringId;
            } else {
              if (LastStringId != StringId) {
                ASSERT(FALSE);
              }
            }
          }
          DEBUG_CODE_END ();
          
        }
      }

      Link = GetNextNode (&Private->ThunkContextListHead, Link);
    }
  } else {
    StringId = *Reference;
    Status = UpdateString (StringPackThunkContext, Rfc4646AsciiLanguage, NewString, &StringId);
  }

  if (!EFI_ERROR (Status)) {
    if (*Reference == 0) {
      *Reference = StringId;
    }
  } else {
    //
    // Only EFI_INVALID_PARAMETER is defined in HII 0.92 specification.
    //
    Status = EFI_INVALID_PARAMETER;
  }
  
  return Status;
}
Esempio n. 21
0
/**
 This function extracts a string from a package already registered with the EFI HII database.

  @param This            A pointer to the EFI_HII_PROTOCOL instance.
  @param Handle          The HII handle on which the string resides.
  @param Token           The string token assigned to the string.
  @param Raw             If TRUE, the string is returned unedited in the internal storage format described
                         above. If false, the string returned is edited by replacing <cr> with <space>
                         and by removing special characters such as the <wide> prefix.
  @param LanguageString  Pointer to a NULL-terminated string containing a single ISO 639-2 language
                         identifier, indicating the language to print. If the LanguageString is empty (starts
                         with a NULL), the default system language will be used to determine the language.
  @param BufferLength    Length of the StringBuffer. If the status reports that the buffer width is too
                         small, this parameter is filled with the length of the buffer needed.
  @param StringBuffer    The buffer designed to receive the characters in the string. Type EFI_STRING is
                         defined in String.

  @retval EFI_INVALID_PARAMETER If input parameter is invalid.
  @retval EFI_BUFFER_TOO_SMALL  If the *BufferLength is too small.
  @retval EFI_SUCCESS           Operation is successful.

**/
EFI_STATUS
EFIAPI
HiiThunkGetString (
  IN     EFI_HII_PROTOCOL           *This,
  IN     FRAMEWORK_EFI_HII_HANDLE   Handle,
  IN     STRING_REF                 Token,
  IN     BOOLEAN                    Raw,
  IN     CHAR16                     *LanguageString,
  IN OUT UINTN                      *BufferLength,
  OUT    EFI_STRING                 StringBuffer
  )
{
  HII_THUNK_PRIVATE_DATA                *Private;
  CHAR8                                 *Iso639AsciiLanguage;
  CHAR8                                 *Rfc4646AsciiLanguage;
  CHAR8                                 *SupportedLanguages;
  CHAR8                                 *PlatformLanguage;
  CHAR8                                 *BestLanguage;
  EFI_HII_HANDLE                        UefiHiiHandle;
  EFI_STATUS                            Status;

  Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);

  Rfc4646AsciiLanguage = NULL;
  SupportedLanguages   = NULL;
  PlatformLanguage     = NULL;
  Status               = EFI_SUCCESS;

  if (LanguageString != NULL) {
    Iso639AsciiLanguage = AllocateZeroPool (StrLen (LanguageString) + 1);
    if (Iso639AsciiLanguage == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
    UnicodeStrToAsciiStr  (LanguageString, Iso639AsciiLanguage);

    //
    // Caller of Framework HII Interface uses the Language Identification String defined 
    // in Iso639. So map it to the Language Identifier defined in RFC4646.
    //
    Rfc4646AsciiLanguage = ConvertLanguagesIso639ToRfc4646 (Iso639AsciiLanguage);
    FreePool (Iso639AsciiLanguage);

    //
    // If Rfc4646AsciiLanguage is NULL, more language mapping must be added to 
    // Iso639ToRfc4646Map.
    //
    ASSERT (Rfc4646AsciiLanguage != NULL);
  }

  UefiHiiHandle = FwHiiHandleToUefiHiiHandle (Private, Handle);
  if (UefiHiiHandle == NULL) {
    Status = EFI_NOT_FOUND;
    goto Done;
  }

  //
  // Get the languages that the package specified by HiiHandle supports
  //
  SupportedLanguages = HiiGetSupportedLanguages (UefiHiiHandle);
  if (SupportedLanguages == NULL) {
    goto Done;
  }

  //
  // Get the current platform language setting
  //
  PlatformLanguage = GetEfiGlobalVariable (L"PlatformLang");

  //
  // Get the best matching language from SupportedLanguages
  //
  BestLanguage = GetBestLanguage (
                   SupportedLanguages, 
                   FALSE,                // RFC 4646 mode
                   (Rfc4646AsciiLanguage != NULL) ? Rfc4646AsciiLanguage : "", // Highest priority 
                   (PlatformLanguage != NULL) ? PlatformLanguage : "",         // Next highest priority
                   SupportedLanguages,   // Lowest priority 
                   NULL
                   );
  if (BestLanguage != NULL) {
    Status = mHiiStringProtocol->GetString (
                                 mHiiStringProtocol,
                                 BestLanguage,
                                 UefiHiiHandle,
                                 Token,
                                 StringBuffer,
                                 BufferLength,
                                 NULL
                                 );
    FreePool (BestLanguage);
  } else {
    Status = EFI_INVALID_PARAMETER;
  }

Done:
	if (Rfc4646AsciiLanguage != NULL) {
    FreePool (Rfc4646AsciiLanguage);
  }

  if (SupportedLanguages != NULL) {
    FreePool (SupportedLanguages);
  }

  if (PlatformLanguage != NULL) {
    FreePool (PlatformLanguage);
  }
  return Status;
}
Esempio n. 22
0
EFI_STATUS
DefineDefaultBootEntries (
  VOID
  )
{
  BDS_LOAD_OPTION*                    BdsLoadOption;
  UINTN                               Size;
  EFI_STATUS                          Status;
  EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol;
  EFI_DEVICE_PATH*                    BootDevicePath;
  UINT8*                              OptionalData;
  UINTN                               OptionalDataSize;
  ARM_BDS_LOADER_ARGUMENTS*           BootArguments;
  ARM_BDS_LOADER_TYPE                 BootType;
  EFI_DEVICE_PATH*                    InitrdPath;
  UINTN                               InitrdSize;
  UINTN                               CmdLineSize;
  UINTN                               CmdLineAsciiSize;
  CHAR16*                             DefaultBootArgument;
  CHAR8*                              AsciiDefaultBootArgument;

  //
  // If Boot Order does not exist then create a default entry
  //
  Size = 0;
  Status = gRT->GetVariable (L"BootOrder", &gEfiGlobalVariableGuid, NULL, &Size, NULL);
  if (Status == EFI_NOT_FOUND) {
    if ((PcdGetPtr(PcdDefaultBootDevicePath) == NULL) || (StrLen ((CHAR16*)PcdGetPtr(PcdDefaultBootDevicePath)) == 0)) {
      return EFI_UNSUPPORTED;
    }

    Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
    if (EFI_ERROR(Status)) {
      // You must provide an implementation of DevicePathFromTextProtocol in your firmware (eg: DevicePathDxe)
      DEBUG((EFI_D_ERROR,"Error: Bds requires DevicePathFromTextProtocol\n"));
      return Status;
    }
    BootDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultBootDevicePath));

    DEBUG_CODE_BEGIN();
      // We convert back to the text representation of the device Path to see if the initial text is correct
      EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;
      CHAR16* DevicePathTxt;

      Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);
      ASSERT_EFI_ERROR(Status);
      DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (BootDevicePath, TRUE, TRUE);

      ASSERT (StrCmp ((CHAR16*)PcdGetPtr(PcdDefaultBootDevicePath), DevicePathTxt) == 0);

      FreePool (DevicePathTxt);
    DEBUG_CODE_END();

    // Create the entry is the Default values are correct
    if (BootDevicePath != NULL) {
      BootType = (ARM_BDS_LOADER_TYPE)PcdGet32 (PcdDefaultBootType);

      // We do not support NULL pointer
      ASSERT (PcdGetPtr (PcdDefaultBootArgument) != NULL);

      //
      // Logic to handle ASCII or Unicode default parameters
      //
      if (*(CHAR8*)PcdGetPtr (PcdDefaultBootArgument) == '\0') {
        CmdLineSize = 0;
        CmdLineAsciiSize = 0;
        DefaultBootArgument = NULL;
        AsciiDefaultBootArgument = NULL;
      } else if (IsUnicodeString ((CHAR16*)PcdGetPtr (PcdDefaultBootArgument))) {
        // The command line is a Unicode string
        DefaultBootArgument = (CHAR16*)PcdGetPtr (PcdDefaultBootArgument);
        CmdLineSize = StrSize (DefaultBootArgument);

        // Initialize ASCII variables
        CmdLineAsciiSize = CmdLineSize / 2;
        AsciiDefaultBootArgument = AllocatePool (CmdLineAsciiSize);
        if (AsciiDefaultBootArgument == NULL) {
          return EFI_OUT_OF_RESOURCES;
        }
        UnicodeStrToAsciiStr ((CHAR16*)PcdGetPtr (PcdDefaultBootArgument), AsciiDefaultBootArgument);
      } else {
        // The command line is a ASCII string
        AsciiDefaultBootArgument = (CHAR8*)PcdGetPtr (PcdDefaultBootArgument);
        CmdLineAsciiSize = AsciiStrSize (AsciiDefaultBootArgument);

        // Initialize ASCII variables
        CmdLineSize = CmdLineAsciiSize * 2;
        DefaultBootArgument = AllocatePool (CmdLineSize);
        if (DefaultBootArgument == NULL) {
          return EFI_OUT_OF_RESOURCES;
        }
        AsciiStrToUnicodeStr (AsciiDefaultBootArgument, DefaultBootArgument);
      }

      if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {
        InitrdPath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultBootInitrdPath));
        InitrdSize = GetDevicePathSize (InitrdPath);

        OptionalDataSize = sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineAsciiSize + InitrdSize;
        BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (OptionalDataSize);
        if (BootArguments == NULL) {
          return EFI_OUT_OF_RESOURCES;
        }
        BootArguments->LinuxArguments.CmdLineSize = CmdLineAsciiSize;
        BootArguments->LinuxArguments.InitrdSize = InitrdSize;

        CopyMem ((VOID*)(BootArguments + 1), AsciiDefaultBootArgument, CmdLineAsciiSize);
        CopyMem ((VOID*)((UINTN)(BootArguments + 1) + CmdLineAsciiSize), InitrdPath, InitrdSize);

        OptionalData = (UINT8*)BootArguments;
      } else {
        OptionalData = (UINT8*)DefaultBootArgument;
        OptionalDataSize = CmdLineSize;
      }

      BootOptionCreate (LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT,
        (CHAR16*)PcdGetPtr(PcdDefaultBootDescription),
        BootDevicePath,
        BootType,
        OptionalData,
        OptionalDataSize,
        &BdsLoadOption
        );
      FreePool (BdsLoadOption);

      if (DefaultBootArgument == (CHAR16*)PcdGetPtr (PcdDefaultBootArgument)) {
        FreePool (AsciiDefaultBootArgument);
      } else if (DefaultBootArgument != NULL) {
        FreePool (DefaultBootArgument);
      }
    } else {
      Status = EFI_UNSUPPORTED;
    }
  }

  return Status;
}
/**

  Publish the smbios type 1.

  @param Event      Event whose notification function is being invoked (gEfiDxeSmmReadyToLockProtocolGuid).
  @param Context    Pointer to the notification functions context, which is implementation dependent.

  @retval None

**/
EFI_STATUS
EFIAPI
AddSmbiosManuCallback (
  IN EFI_EVENT  Event,
  IN VOID       *Context
  )
{

  CHAR8                             *OptionalStrStart;
  UINTN                             ManuStrLen;
  UINTN                             VerStrLen;
  UINTN                             PdNameStrLen;
  UINTN                             SerialNumStrLen;
  UINTN                             SkuNumberStrLen;
  UINTN				                FamilyNameStrLen;
  EFI_STATUS                        Status;
  EFI_STRING                        Manufacturer;
  EFI_STRING                        ProductName;
  EFI_STRING                        Version;
  EFI_STRING                        SerialNumber;
  EFI_STRING                        SkuNumber;
  EFI_STRING			            FamilyName;
  STRING_REF                        TokenToGet;
  EFI_SMBIOS_HANDLE                 SmbiosHandle;
  SMBIOS_TABLE_TYPE1                *SmbiosRecord;
  EFI_MISC_SYSTEM_MANUFACTURER      *ForType1InputData;
  EFI_SMBIOS_PROTOCOL               *Smbios;
  CHAR16                            Buffer[40];
  
  CHAR16                            *MacStr; 
  EFI_HANDLE                        *Handles;
  UINTN                             BufferSize;
  CHAR16                            PlatformNameBuffer[40];

  ForType1InputData = (EFI_MISC_SYSTEM_MANUFACTURER *)Context;

  //
  // First check for invalid parameters.
  //
  if (Context == NULL || mPlatformInfo == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID *) &Smbios);
  ASSERT_EFI_ERROR (Status);


  if (BOARD_ID_MINNOW2_COMPATIBLE == mPlatformInfo->BoardId) {
    // Detect the board is compatible board platform
    UnicodeSPrint (PlatformNameBuffer, sizeof (PlatformNameBuffer),L"%s",L"Minnowboard Compatible ");
  } else {
    UnicodeSPrint (PlatformNameBuffer, sizeof (PlatformNameBuffer),L"%s",L"Minnowboard Max ");
  }

  //
  // Silicon Steppings
  //
  switch (PchStepping()) {
    case PchA0:
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s%s", PlatformNameBuffer, L"A0 PLATFORM");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL);
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"A0");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL);
      DEBUG ((EFI_D_ERROR, "A0 Stepping Detected\n"));
      break;
    case PchA1:
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s%s", PlatformNameBuffer, L"A1 PLATFORM");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL);
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"A1");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL);
      DEBUG ((EFI_D_ERROR, "A1 Stepping Detected\n"));
      break;
    case PchB0:
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s%s", PlatformNameBuffer, L"B0 PLATFORM");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL);
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"B0");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL);
      DEBUG ((EFI_D_ERROR, "B0 Stepping Detected\n"));
      break;
    case PchB1:
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s%s", PlatformNameBuffer, L"B1 PLATFORM");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL);
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"B1");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL);
      DEBUG ((EFI_D_ERROR, "B1 Stepping Detected\n"));
      break;
    case PchB2:
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s%s", PlatformNameBuffer, L"B2 PLATFORM");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL);
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"B2");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL);
      DEBUG ((EFI_D_ERROR, "B2 Stepping Detected\n"));
      break;
    case PchB3:
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s%s", PlatformNameBuffer, L"B3 PLATFORM");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL);
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"B3");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL);
      DEBUG ((EFI_D_ERROR, "B3 Stepping Detected\n"));
      break;
    case PchC0:
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s%s", PlatformNameBuffer, L"C0 PLATFORM");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL);
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"C0");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL);
      DEBUG ((EFI_D_ERROR, "C0 Stepping Detected\n"));
      break;
   case PchD0:
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s%s", PlatformNameBuffer, L"D0 PLATFORM");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), Buffer, NULL);
      UnicodeSPrint (Buffer, sizeof (Buffer),L"%s",L"D0");
      HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_VERSION), Buffer, NULL);
      DEBUG ((EFI_D_ERROR, "D0 Stepping Detected\n"));
      break;
    default:
      DEBUG ((EFI_D_ERROR, "Unknow Stepping Detected\n"));
      break;
    }

  if (BOARD_ID_MINNOW2_COMPATIBLE == mPlatformInfo->BoardId) {
    UnicodeSPrint (Buffer, sizeof (Buffer),L"Compatible Vendor");
    HiiSetString(mHiiHandle,STRING_TOKEN(STR_MISC_SYSTEM_MANUFACTURER), Buffer, NULL);
  }
  TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_MANUFACTURER);
  Manufacturer = SmbiosMiscGetString (TokenToGet);
  ManuStrLen = StrLen(Manufacturer);
  if (ManuStrLen > SMBIOS_STRING_MAX_LENGTH) {
    return EFI_UNSUPPORTED;
  }

  TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_PRODUCT_NAME);
  ProductName = SmbiosMiscGetString (TokenToGet);
  PdNameStrLen = StrLen(ProductName);
  if (PdNameStrLen > SMBIOS_STRING_MAX_LENGTH) {
    return EFI_UNSUPPORTED;
  }

  TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_VERSION);
  Version = SmbiosMiscGetString (TokenToGet);
  VerStrLen = StrLen(Version);
  if (VerStrLen > SMBIOS_STRING_MAX_LENGTH) {
    return EFI_UNSUPPORTED;
  }

  //
  //Get handle infomation
  //
  BufferSize = 0;
  Handles = NULL;
  Status = gBS->LocateHandle (
                  ByProtocol, 
                  &gEfiSimpleNetworkProtocolGuid,
                  NULL,
                  &BufferSize,
                  Handles
                  );

  if (Status == EFI_BUFFER_TOO_SMALL) {
  	Handles = AllocateZeroPool(BufferSize);
  	if (Handles == NULL) {
  		return (EFI_OUT_OF_RESOURCES);
  	}
  	Status = gBS->LocateHandle(
  	                ByProtocol,
  	                &gEfiSimpleNetworkProtocolGuid,
  	                NULL,
  	                &BufferSize,
  	                Handles
  	                );
 }
 	                
  //
  //Get the MAC string
  //
  Status = NetLibGetMacString (
             *Handles,
             NULL,
             &MacStr
             );
  if (EFI_ERROR (Status)) {	
    return Status;
  }
  SerialNumber = MacStr; 
  SerialNumStrLen = StrLen(SerialNumber);
  if (SerialNumStrLen > SMBIOS_STRING_MAX_LENGTH) {
    return EFI_UNSUPPORTED;
  }
  TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_SKU_NUMBER);
  SkuNumber = SmbiosMiscGetString (TokenToGet);
  SkuNumberStrLen = StrLen(SkuNumber);
  if (SkuNumberStrLen > SMBIOS_STRING_MAX_LENGTH) {
    return EFI_UNSUPPORTED;
  }
  TokenToGet = STRING_TOKEN (STR_MISC_SYSTEM_FAMILY_NAME1);
  FamilyName = SmbiosMiscGetString (TokenToGet);
  FamilyNameStrLen = StrLen(FamilyName);
  if (FamilyNameStrLen > SMBIOS_STRING_MAX_LENGTH) {
    return EFI_UNSUPPORTED;
  }

  //
  // Two zeros following the last string.
  //
  SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE1) + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + SkuNumberStrLen + 1 + FamilyNameStrLen + 1 + 1);
  ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE1) + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + SkuNumberStrLen + 1 + FamilyNameStrLen + 1 + 1);

  SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_SYSTEM_INFORMATION;
  SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE1);

  //
  // Make handle chosen by smbios protocol.add automatically.
  //
  SmbiosRecord->Hdr.Handle = 0;

  //
  // Manu will be the 1st optional string following the formatted structure.
  //
  SmbiosRecord->Manufacturer = 1;

  //
  // ProductName will be the 2nd optional string following the formatted structure.
  //
  SmbiosRecord->ProductName = 2;

  //
  // Version will be the 3rd optional string following the formatted structure.
  //
  SmbiosRecord->Version = 3;

  //
  // Version will be the 4th optional string following the formatted structure.
  //
  SmbiosRecord->SerialNumber = 4;

  SmbiosRecord->SKUNumber= 5;
  SmbiosRecord->Family= 6;

  //
  // Unique UUID
  //
  ForType1InputData->SystemUuid.Data1 = PcdGet32 (PcdProductSerialNumber);
  ForType1InputData->SystemUuid.Data4[0] = PcdGet8 (PcdEmmcManufacturerId);

  CopyMem ((UINT8 *) (&SmbiosRecord->Uuid),&ForType1InputData->SystemUuid,16);

  SmbiosRecord->WakeUpType = (UINT8)ForType1InputData->SystemWakeupType;

  OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
  UnicodeStrToAsciiStr(Manufacturer, OptionalStrStart);
  UnicodeStrToAsciiStr(ProductName, OptionalStrStart + ManuStrLen + 1);
  UnicodeStrToAsciiStr(Version, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1);
  UnicodeStrToAsciiStr(SerialNumber, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1);

  UnicodeStrToAsciiStr(SkuNumber, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1 +  VerStrLen + 1 + SerialNumStrLen + 1);
  UnicodeStrToAsciiStr(FamilyName, OptionalStrStart + ManuStrLen + 1 + PdNameStrLen + 1 + VerStrLen + 1 + SerialNumStrLen + 1 + SkuNumberStrLen +1);

  //
  // Now we have got the full smbios record, call smbios protocol to add this record.
  //
  SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
  Status = Smbios-> Add(
                      Smbios,
                      NULL,
                      &SmbiosHandle,
                      (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
                      );
  FreePool(SmbiosRecord);
  return Status;
}
Esempio n. 24
0
/**
  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[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  @param[in]  Action             Specifies the type of action taken by the browser.
  @param[in]  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 enerated the callback.
  @param[in]  Type               The type of value for the question.
  @param[in]  Value              A pointer to the data being sent to the original
                                 exporting driver.
  @param[out]  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.Currently not implemented.
  @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
  @retval Others                 Other errors as indicated.
**/
EFI_STATUS
EFIAPI
Ip4FormCallback (
  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
  IN  EFI_BROWSER_ACTION                     Action,
  IN  EFI_QUESTION_ID                        QuestionId,
  IN  UINT8                                  Type,
  IN  EFI_IFR_TYPE_VALUE                     *Value,
  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest
  )
{
  IP4_CONFIG_INSTANCE       *Ip4ConfigInstance;
  CHAR8                     Ip4String[IP4_STR_MAX_SIZE];
  IP4_CONFIG_IFR_NVDATA     *IfrFormNvData;
  EFI_IP_ADDRESS            HostIp;
  EFI_IP_ADDRESS            SubnetMask;
  EFI_IP_ADDRESS            Gateway;
  EFI_STATUS                Status;
  EFI_INPUT_KEY             Key;

  Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);

  IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));
  if (IfrFormNvData == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  //
  // Retrive uncommitted data from Browser
  //
  if (!HiiGetBrowserData (&mNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE, sizeof (IP4_CONFIG_IFR_NVDATA), (UINT8 *) IfrFormNvData)) {
    FreePool (IfrFormNvData);
    return EFI_NOT_FOUND;
  }

  Status = EFI_SUCCESS;

  switch (QuestionId) {

  case KEY_ENABLE:
    if (IfrFormNvData->Configure == 0) {
      Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = FALSE;
    } else {
      Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = TRUE;
    }
    break;

  case KEY_DHCP_ENABLE:
    if (IfrFormNvData->DhcpEnable == 0) {
      Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = FALSE;
    } else {
      Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = TRUE;
    }

    break;

  case KEY_LOCAL_IP:
    UnicodeStrToAsciiStr (IfrFormNvData->StationAddress, Ip4String);
    Status = Ip4AsciiStrToIp (Ip4String, &HostIp.v4);
    if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {
      CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);
      Status = EFI_INVALID_PARAMETER;
    } else {
      CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, &HostIp.v4, sizeof (HostIp.v4));
    }

    break;

  case KEY_SUBNET_MASK:
    UnicodeStrToAsciiStr (IfrFormNvData->SubnetMask, Ip4String);
    Status = Ip4AsciiStrToIp (Ip4String, &SubnetMask.v4);
    if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
      CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid SubnetMask!", NULL);
      Status = EFI_INVALID_PARAMETER;
    } else {
      CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));
    }

    break;

  case KEY_GATE_WAY:
    UnicodeStrToAsciiStr (IfrFormNvData->GatewayAddress, Ip4String);
    Status = Ip4AsciiStrToIp (Ip4String, &Gateway.v4);
    if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {
      CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);
      Status = EFI_INVALID_PARAMETER;
    } else {
      CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, &Gateway.v4, sizeof (Gateway.v4));
    }

    break;

  case KEY_SAVE_CHANGES:

    Status = Ip4ConfigConvertIfrNvDataToDeviceConfigData (Ip4ConfigInstance);

    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;

    break;

  default:

    break;
  }

  if (!EFI_ERROR (Status)) {
    //
    // Pass changed uncommitted data back to Form Browser
    //
    HiiSetBrowserData (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, sizeof (IP4_CONFIG_IFR_NVDATA), (UINT8 *) IfrFormNvData, NULL);
  }

  FreePool (IfrFormNvData);

  return Status;
}
Esempio n. 25
0
File: Dp.c Progetto: OznOg/edk2
/**
  Dump performance data.
  
  @param[in]  ImageHandle     The image handle.
  @param[in]  SystemTable     The system table.

  @retval EFI_SUCCESS            Command completed successfully.
  @retval EFI_INVALID_PARAMETER  Command usage error.
  @retval EFI_ABORTED            The user aborts the operation.
  @retval value                  Unknown error.
**/
EFI_STATUS
EFIAPI
InitializeDp (
  IN EFI_HANDLE               ImageHandle,
  IN EFI_SYSTEM_TABLE         *SystemTable
  )
{
  UINT64                    Freq;
  UINT64                    Ticker;
  UINT32                    ListIndex;
  
  LIST_ENTRY                *ParamPackage;
  CONST CHAR16              *CmdLineArg;
  EFI_STRING                StringPtr;
  UINTN                     Number2Display;

  EFI_STATUS                Status;
  BOOLEAN                   SummaryMode;
  BOOLEAN                   VerboseMode;
  BOOLEAN                   AllMode;
  BOOLEAN                   RawMode;
  BOOLEAN                   TraceMode;
  BOOLEAN                   ProfileMode;
  BOOLEAN                   ExcludeMode;
  BOOLEAN                   CumulativeMode;
  CONST CHAR16              *CustomCumulativeToken;
  PERF_CUM_DATA             *CustomCumulativeData;

  EFI_STRING                StringDpOptionQh;
  EFI_STRING                StringDpOptionLh;
  EFI_STRING                StringDpOptionUh;
  EFI_STRING                StringDpOptionLv;
  EFI_STRING                StringDpOptionUs;
  EFI_STRING                StringDpOptionLs;
  EFI_STRING                StringDpOptionUa;
  EFI_STRING                StringDpOptionUr;
  EFI_STRING                StringDpOptionUt;
  EFI_STRING                StringDpOptionUp;
  EFI_STRING                StringDpOptionLx;
  EFI_STRING                StringDpOptionLn;
  EFI_STRING                StringDpOptionLt;
  EFI_STRING                StringDpOptionLi;
  EFI_STRING                StringDpOptionLc;
  
  SummaryMode     = FALSE;
  VerboseMode     = FALSE;
  AllMode         = FALSE;
  RawMode         = FALSE;
  TraceMode       = FALSE;
  ProfileMode     = FALSE;
  ExcludeMode     = FALSE;
  CumulativeMode = FALSE;
  CustomCumulativeData = NULL;

  StringDpOptionQh = NULL;
  StringDpOptionLh = NULL;
  StringDpOptionUh = NULL;
  StringDpOptionLv = NULL;
  StringDpOptionUs = NULL;
  StringDpOptionLs = NULL;
  StringDpOptionUa = NULL;
  StringDpOptionUr = NULL;
  StringDpOptionUt = NULL;
  StringDpOptionUp = NULL;
  StringDpOptionLx = NULL;
  StringDpOptionLn = NULL;
  StringDpOptionLt = NULL;
  StringDpOptionLi = NULL;
  StringDpOptionLc = NULL;
  StringPtr        = NULL;

  // Get DP's entry time as soon as possible.
  // This is used as the Shell-Phase end time.
  //
  Ticker  = GetPerformanceCounter ();

  // Register our string package with HII and return the handle to it.
  //
  gHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, DPStrings, NULL);
  ASSERT (gHiiHandle != NULL);

  // Initial the command list
  //
  InitialShellParamList ();
  
/****************************************************************************
****            Process Command Line arguments                           ****
****************************************************************************/
  Status = ShellCommandLineParse (DpParamList, &ParamPackage, NULL, TRUE);

  if (EFI_ERROR(Status)) {
    PrintToken (STRING_TOKEN (STR_DP_INVALID_ARG));
    ShowHelp();
  }
  else {
    StringDpOptionQh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_QH), NULL);
    StringDpOptionLh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LH), NULL);
    StringDpOptionUh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UH), NULL);
    
    if (ShellCommandLineGetFlag (ParamPackage, StringDpOptionQh)  ||
        ShellCommandLineGetFlag (ParamPackage, StringDpOptionLh)  ||
        ShellCommandLineGetFlag (ParamPackage, StringDpOptionUh))
    {
      ShowHelp();
    }
    else {
      StringDpOptionLv = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LV), NULL);
      StringDpOptionUs = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_US), NULL);
      StringDpOptionLs = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LS), NULL);
      StringDpOptionUa = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UA), NULL);
      StringDpOptionUr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UR), NULL);
      StringDpOptionUt = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UT), NULL);
      StringDpOptionUp = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UP), NULL);
      StringDpOptionLx = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LX), NULL);
      StringDpOptionLn = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LN), NULL);
      StringDpOptionLt = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LT), NULL);
      StringDpOptionLi = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LI), NULL);
      StringDpOptionLc = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LC), NULL);
      
      // Boolean Options
      // 
      VerboseMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLv);
      SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, StringDpOptionUs) ||
                    ShellCommandLineGetFlag (ParamPackage, StringDpOptionLs));
      AllMode     = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUa);
      RawMode     = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUr);
#if PROFILING_IMPLEMENTED
      TraceMode   = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUt);
      ProfileMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUp);
#endif  // PROFILING_IMPLEMENTED
      ExcludeMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLx);
      mShowId     =  ShellCommandLineGetFlag (ParamPackage, StringDpOptionLi);
      CumulativeMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLc);

      // Options with Values
      CmdLineArg  = ShellCommandLineGetValue (ParamPackage, StringDpOptionLn);
      if (CmdLineArg == NULL) {
        Number2Display = DEFAULT_DISPLAYCOUNT;
      }
      else {
        Number2Display = StrDecimalToUintn(CmdLineArg);
        if (Number2Display == 0) {
          Number2Display = MAXIMUM_DISPLAYCOUNT;
        }
      }
      CmdLineArg  = ShellCommandLineGetValue (ParamPackage, StringDpOptionLt);
      if (CmdLineArg == NULL) {
        mInterestThreshold = DEFAULT_THRESHOLD;  // 1ms := 1,000 us
      }
      else {
        mInterestThreshold = StrDecimalToUint64(CmdLineArg);
      }
      // Handle Flag combinations and default behaviors
      // If both TraceMode and ProfileMode are FALSE, set them both to TRUE
      if ((! TraceMode) && (! ProfileMode)) {
        TraceMode   = TRUE;
#if PROFILING_IMPLEMENTED
        ProfileMode = TRUE;
#endif  // PROFILING_IMPLEMENTED
      }

  //
  // Init the custom cumulative data.
  //
  CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, StringDpOptionLc);
  if (CustomCumulativeToken != NULL) {
    CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA));
    ASSERT (CustomCumulativeData != NULL);
    CustomCumulativeData->MinDur = 0;
    CustomCumulativeData->MaxDur = 0;
    CustomCumulativeData->Count  = 0;
    CustomCumulativeData->Duration = 0;
    CustomCumulativeData->Name   = AllocateZeroPool (StrLen (CustomCumulativeToken) + 1);
    UnicodeStrToAsciiStr (CustomCumulativeToken, CustomCumulativeData->Name);
  }

/****************************************************************************
****            Timer specific processing                                ****
****************************************************************************/
      // Get the Performance counter characteristics:
      //          Freq = Frequency in Hz
      //    StartCount = Value loaded into the counter when it starts counting
      //      EndCount = Value counter counts to before it needs to be reset
      //
      Freq = GetPerformanceCounterProperties (&TimerInfo.StartCount, &TimerInfo.EndCount);

      // Convert the Frequency from Hz to KHz
      TimerInfo.Frequency = (UINT32)DivU64x32 (Freq, 1000);

      // Determine in which direction the performance counter counts.
      TimerInfo.CountUp = (BOOLEAN) (TimerInfo.EndCount >= TimerInfo.StartCount);

/****************************************************************************
****            Print heading                                            ****
****************************************************************************/
      // print DP's build version
      PrintToken (STRING_TOKEN (STR_DP_BUILD_REVISION), DP_MAJOR_VERSION, DP_MINOR_VERSION);

      // print performance timer characteristics
      PrintToken (STRING_TOKEN (STR_DP_KHZ), TimerInfo.Frequency);         // Print Timer frequency in KHz

      if ((VerboseMode)   &&
          (! RawMode)
         ) {
        StringPtr = HiiGetString (gHiiHandle,
                      (EFI_STRING_ID) (TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)),
                      NULL);
        ASSERT (StringPtr != NULL);
        PrintToken (STRING_TOKEN (STR_DP_TIMER_PROPERTIES),   // Print Timer count range and direction
                    StringPtr,
                    TimerInfo.StartCount,
                    TimerInfo.EndCount
                    );
        PrintToken (STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), mInterestThreshold);
      }

/* **************************************************************************
****            Print Sections based on command line options
****
****  Option modes have the following priority:
****    v Verbose     --  Valid in combination with any other options
****    t Threshold   --  Modifies All, Raw, and Cooked output
****                      Default is 0 for All and Raw mode
****                      Default is DEFAULT_THRESHOLD for "Cooked" mode
****    n Number2Display  Used by All and Raw mode.  Otherwise ignored.
****    A All         --  R and S options are ignored
****    R Raw         --  S option is ignored
****    s Summary     --  Modifies "Cooked" output only
****    Cooked (Default)
****
****  The All, Raw, and Cooked modes are modified by the Trace and Profile
****  options.
****    !T && !P  := (0) Default, Both are displayed
****     T && !P  := (1) Only Trace records are displayed
****    !T &&  P  := (2) Only Profile records are displayed
****     T &&  P  := (3) Same as Default, both are displayed
****************************************************************************/
      GatherStatistics (CustomCumulativeData);
      if (CumulativeMode) {                       
        ProcessCumulative (CustomCumulativeData);
      } else if (AllMode) {
        if (TraceMode) {
          Status = DumpAllTrace( Number2Display, ExcludeMode);
          if (Status == EFI_ABORTED) {
            goto Done;
          }
        }
        if (ProfileMode) {
          DumpAllProfile( Number2Display, ExcludeMode);
        }
      }
      else if (RawMode) {
        if (TraceMode) {
          Status = DumpRawTrace( Number2Display, ExcludeMode);
          if (Status == EFI_ABORTED) {
            goto Done;
          }
        }
        if (ProfileMode) {
          DumpRawProfile( Number2Display, ExcludeMode);
        }
      }
      else {
        //------------- Begin Cooked Mode Processing
        if (TraceMode) {
          ProcessPhases ( Ticker );
          if ( ! SummaryMode) {
            Status = ProcessHandles ( ExcludeMode);
            if (Status == EFI_ABORTED) {
              goto Done;
            }

            Status = ProcessPeims ();
            if (Status == EFI_ABORTED) {
              goto Done;
            }

            Status = ProcessGlobal ();
            if (Status == EFI_ABORTED) {
              goto Done;
            }

            ProcessCumulative (NULL);
          }
        }
        if (ProfileMode) {
          DumpAllProfile( Number2Display, ExcludeMode);
        }
      } //------------- End of Cooked Mode Processing
      if ( VerboseMode || SummaryMode) {
        DumpStatistics();
      }
    }
  }

Done:

  //
  // Free the memory allocate from HiiGetString
  //
  ListIndex = 0;
  while (DpParamList[ListIndex].Name != NULL) {
    FreePool (DpParamList[ListIndex].Name);
    ListIndex ++;
  }  
  FreePool (DpParamList);

  SafeFreePool (StringDpOptionQh);
  SafeFreePool (StringDpOptionLh);
  SafeFreePool (StringDpOptionUh);
  SafeFreePool (StringDpOptionLv);
  SafeFreePool (StringDpOptionUs);
  SafeFreePool (StringDpOptionLs);
  SafeFreePool (StringDpOptionUa);
  SafeFreePool (StringDpOptionUr);
  SafeFreePool (StringDpOptionUt);
  SafeFreePool (StringDpOptionUp);
  SafeFreePool (StringDpOptionLx);
  SafeFreePool (StringDpOptionLn);
  SafeFreePool (StringDpOptionLt);
  SafeFreePool (StringDpOptionLi);
  SafeFreePool (StringDpOptionLc);
  SafeFreePool (StringPtr);
  SafeFreePool (mPrintTokenBuffer);

  if (CustomCumulativeData != NULL) {
    SafeFreePool (CustomCumulativeData->Name);
  }
  SafeFreePool (CustomCumulativeData);

  HiiRemovePackages (gHiiHandle);
  return Status;
}
Esempio n. 26
0
EFI_STATUS
FileOpen (
  IN  EFI_FILE    *File,
  OUT EFI_FILE    **NewHandle,
  IN  CHAR16      *FileName,
  IN  UINT64      OpenMode,
  IN  UINT64      Attributes
  )
{
  SEMIHOST_FCB  *FileFcb = NULL;
  EFI_STATUS    Status   = EFI_SUCCESS;
  UINTN         SemihostHandle;
  CHAR8         *AsciiFileName;
  UINT32        SemihostMode;
  BOOLEAN       IsRoot;

  if ((FileName == NULL) || (NewHandle == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  // Semihost interface requires ASCII filenames
  AsciiFileName = AllocatePool ((StrLen (FileName) + 1) * sizeof (CHAR8));
  if (AsciiFileName == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  UnicodeStrToAsciiStr (FileName, AsciiFileName);

  if ((AsciiStrCmp (AsciiFileName, "\\") == 0) ||
      (AsciiStrCmp (AsciiFileName, "/")  == 0) ||
      (AsciiStrCmp (AsciiFileName, "")   == 0) ||
      (AsciiStrCmp (AsciiFileName, ".")  == 0)) {
    // Opening '/', '\', '.', or the NULL pathname is trying to open the root directory
    IsRoot = TRUE;

    // Root directory node doesn't have a name.
    FreePool (AsciiFileName);
    AsciiFileName = NULL;
  } else {
    // Translate EFI_FILE_MODE into Semihosting mode
    if (OpenMode & EFI_FILE_MODE_WRITE) {
      SemihostMode = SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY;
    } else if (OpenMode & EFI_FILE_MODE_READ) {
      SemihostMode = SEMIHOST_FILE_MODE_READ  | SEMIHOST_FILE_MODE_BINARY;
    } else {
      return EFI_UNSUPPORTED;
    }

    // Add the creation flag if necessary
    if (OpenMode & EFI_FILE_MODE_CREATE) {
      SemihostMode |= SEMIHOST_FILE_MODE_CREATE;
    }

    // Call the semihosting interface to open the file.
    Status = SemihostFileOpen (AsciiFileName, SemihostMode, &SemihostHandle);
    if (EFI_ERROR(Status)) {
      return Status;
    }
    
    IsRoot = FALSE;
  }

  // Allocate a control block and fill it
  FileFcb = AllocateFCB ();
  if (FileFcb == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  FileFcb->FileName       = AsciiFileName;
  FileFcb->SemihostHandle = SemihostHandle;
  FileFcb->Position       = 0;
  FileFcb->IsRoot         = IsRoot;

  InsertTailList (&gFileList, &FileFcb->Link);

  *NewHandle = &FileFcb->File;

  return Status;
}
Esempio n. 27
0
/**
  Fill a standard Smbios string field. 
  
  This function will convert the unicode string to single byte chars, and only
  English language is supported.
  This function changes the Structure pointer value of the structure node, 
  which should be noted by Caller.
  
  @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
  @param Offset           Offset of SMBIOS record which RecordData will be filled.
  @param RecordData       RecordData buffer will be filled.
  @param RecordDataSize   The size of RecordData buffer.
  
  @retval EFI_INVALID_PARAMETER   RecordDataSize is too larger
  @retval EFI_OUT_OF_RESOURCES    No memory to allocate new buffer for string
  @retval EFI_SUCCESS             Sucess append string for a SMBIOS record.
**/
EFI_STATUS
SmbiosFldString (
  IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
  IN      UINT32                    Offset,
  IN      VOID                      *RecordData,
  IN      UINT32                    RecordDataSize
  )
{
  EFI_STATUS              Status;
  UINT16                  *Data;
  CHAR8                   AsciiData[SMBIOS_STRING_MAX_LENGTH];
  UINT8                   CountOfStrings;
  UINTN                   OrigStringNumber;
  EFI_SMBIOS_PROTOCOL     *Smbios;
  EFI_SMBIOS_HANDLE       SmbiosHandle;
  UINT32                  OrigStructureSize;
  UINTN                   NewStructureSize;
  EFI_SMBIOS_TABLE_HEADER *NewRecord;
  UINT32                  StringLength;
  
  Status            = EFI_SUCCESS;
  OrigStringNumber  = 0;
  OrigStructureSize = 0;

  //
  // if we have a NULL token,
  //
  if (0 == *((STRING_REF *) RecordData)) {
    *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + Offset) = 0;
    return EFI_SUCCESS;
  }
  
  //
  // Get the String from the Hii Database
  //
  Data = HiiGetPackageString (
             &(StructureNode->ProducerName),
             *((EFI_STRING_ID *) RecordData),
             NULL
             );
  if (Data == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  StringLength = (UINT32)StrLen (Data);
  //
  // Count the string size including the terminating 0.
  //
  if (StringLength == 0) {
    *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + Offset) = 0;
    FreePool (Data);
    return EFI_SUCCESS;
  }
  
  if (StringLength > SMBIOS_STRING_MAX_LENGTH) {
    //
    // Too long a string
    //
    FreePool (Data);
    return EFI_INVALID_PARAMETER;
  }
    
  Smbios = GetSmbiosProtocol();
  ASSERT (Smbios != NULL);
  
  //
  // Convert Unicode string to Ascii string which only supported by SMBIOS.
  //
  ZeroMem (AsciiData, SMBIOS_STRING_MAX_LENGTH);
  UnicodeStrToAsciiStr (Data, AsciiData);
  
  //
  // if the field at offset is already filled with some value,
  // find out the string it points to
  //
  OrigStringNumber = *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + Offset);
  if (OrigStringNumber != 0) {
    DEBUG ((EFI_D_ERROR, "[SMBIOSThunk] Update %dth string for type[%d],offset[0x%x],handle[0x%x] to [%s]\n", 
            OrigStringNumber, StructureNode->SmbiosType, Offset, StructureNode->SmbiosHandle, AsciiData));  
    
    //
    // If original string number is not zero, just update string
    //
    Status = Smbios->UpdateString (Smbios, &StructureNode->SmbiosHandle, &OrigStringNumber, AsciiData);
    if (EFI_ERROR (Status)) {
      DEBUG ((EFI_D_ERROR, "[SMBIOSThunk] Fail to update %dth string in offset 0x%x for handle:0x%x type:0x%x\n", 
             OrigStringNumber, Offset, StructureNode->SmbiosHandle, StructureNode->SmbiosType));
      ASSERT_EFI_ERROR (Status);
      return Status;
    }
  } else {
    //
    // If the string has not been filled in SMBIOS database, remove it and add again
    // with string appended.
    //
    Status = GetSmbiosStructureSize (StructureNode->Structure, &OrigStructureSize, &CountOfStrings);
    ASSERT_EFI_ERROR (Status);
    
    if (CountOfStrings == 0) {
      NewStructureSize = OrigStructureSize + StringLength;
    } else {
      NewStructureSize = OrigStructureSize + StringLength + 1;
    }
    
    NewRecord = AllocateZeroPool (NewStructureSize);
    if (NewRecord == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
    CopyMem (NewRecord, StructureNode->Structure, OrigStructureSize);
    
    //
    // Copy new string into tail of original SMBIOS record buffer.
    //
    if (CountOfStrings == 0) {
      AsciiStrCpy ((CHAR8 *)NewRecord + OrigStructureSize - 2, AsciiData);
    } else {
      AsciiStrCpy ((CHAR8 *)NewRecord + OrigStructureSize - 1, AsciiData);
    }
    DEBUG ((EFI_D_ERROR, "[SMBIOSThunk] Type(%d) offset(0x%x) StringNumber:%d\n", 
            StructureNode->SmbiosType, Offset, CountOfStrings + 1));
    //
    // Update string reference number
    //
    *(UINT8 *) ((UINT8 *) NewRecord + Offset) = (UINT8) (CountOfStrings + 1);
    SmbiosHandle = StructureNode->SmbiosHandle;
    
    //
    // Remove original SMBIOS record and add new one
    //
    Status = Smbios->Remove (Smbios, StructureNode->SmbiosHandle);
    ASSERT_EFI_ERROR (Status);
    
    //
    // Add new SMBIOS record
    //
    Status = Smbios->Add (Smbios, NULL, &SmbiosHandle, NewRecord);
    ASSERT_EFI_ERROR (Status);
    
    StructureNode->SmbiosHandle = SmbiosHandle;
    
    FreePool (NewRecord);
  }
  
  //
  // The SMBIOS record buffer maybe re-allocated in SMBIOS database,
  // so update cached buffer pointer in DataHub structure list.
  //
  StructureNode->Structure = GetSmbiosBufferFromHandle (
                               StructureNode->SmbiosHandle, 
                               StructureNode->SmbiosType,
                               NULL
                               );
  ASSERT (StructureNode->Structure != NULL);
  
  //
  // The string update action maybe lead the record is re-allocated in SMBIOS database
  // so update cached record pointer
  //
  Status = GetSmbiosStructureSize (StructureNode->Structure, &StructureNode->StructureSize, &CountOfStrings);
  ASSERT_EFI_ERROR (Status);
  
  return EFI_SUCCESS;
}
Esempio n. 28
0
/**
  The Request() function queues an HTTP request to this HTTP instance.

  Similar to Transmit() function in the EFI TCP driver. When the HTTP request is sent
  successfully, or if there is an error, Status in token will be updated and Event will
  be signaled.

  @param[in]  This                Pointer to EFI_HTTP_PROTOCOL instance.
  @param[in]  Token               Pointer to storage containing HTTP request token.

  @retval EFI_SUCCESS             Outgoing data was processed.
  @retval EFI_NOT_STARTED         This EFI HTTP Protocol instance has not been started.
  @retval EFI_DEVICE_ERROR        An unexpected system or network error occurred.
  @retval EFI_TIMEOUT             Data was dropped out of the transmit or receive queue.
  @retval EFI_OUT_OF_RESOURCES    Could not allocate enough system resources.
  @retval EFI_UNSUPPORTED         The HTTP method is not supported in current
                                  implementation.
  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
                                  This is NULL.
                                  Token->Message is NULL.
                                  Token->Message->Body is not NULL,
                                  Token->Message->BodyLength is non-zero, and
                                  Token->Message->Data is NULL, but a previous call to
                                  Request()has not been completed successfully.
**/
EFI_STATUS
EFIAPI
EfiHttpRequest (
  IN  EFI_HTTP_PROTOCOL         *This,
  IN  EFI_HTTP_TOKEN            *Token
  )
{
  EFI_HTTP_MESSAGE              *HttpMsg;
  EFI_HTTP_REQUEST_DATA         *Request;
  VOID                          *UrlParser;
  EFI_STATUS                    Status;
  CHAR8                         *HostName;
  UINT16                        RemotePort;
  HTTP_PROTOCOL                 *HttpInstance;
  BOOLEAN                       Configure;
  BOOLEAN                       ReConfigure;
  CHAR8                         *RequestStr;
  CHAR8                         *Url;
  CHAR16                        *HostNameStr;
  HTTP_TOKEN_WRAP               *Wrap;
  HTTP_TCP_TOKEN_WRAP           *TcpWrap;

  if ((This == NULL) || (Token == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  HttpMsg = Token->Message;
  if ((HttpMsg == NULL) || (HttpMsg->Headers == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Current implementation does not support POST/PUT method.
  // If future version supports these two methods, Request could be NULL for a special case that to send large amounts
  // of data. For this case, the implementation need check whether previous call to Request() has been completed or not.
  // 
  //
  Request = HttpMsg->Data.Request;
  if ((Request == NULL) || (Request->Url == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Only support GET and HEAD method in current implementation.
  //
  if ((Request->Method != HttpMethodGet) && (Request->Method != HttpMethodHead)) {
    return EFI_UNSUPPORTED;
  }

  HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
  ASSERT (HttpInstance != NULL);

  if (HttpInstance->State < HTTP_STATE_HTTP_CONFIGED) {
    return EFI_NOT_STARTED;
  }

  if (HttpInstance->LocalAddressIsIPv6) {
    return EFI_UNSUPPORTED;
  }

  //
  // Check whether the token already existed.
  //
  if (EFI_ERROR (NetMapIterate (&HttpInstance->TxTokens, HttpTokenExist, Token))) {
    return EFI_ACCESS_DENIED;   
  }  

  Url         = NULL;
  HostName    = NULL;
  Wrap        = NULL;
  HostNameStr = NULL;
  TcpWrap     = NULL;

  //
  // Parse the URI of the remote host.
  //
  Url = AllocatePool (StrLen (Request->Url) + 1);
  if (Url == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  UnicodeStrToAsciiStr (Request->Url, Url);
  UrlParser = NULL;
  Status = HttpParseUrl (Url, (UINT32) AsciiStrLen (Url), FALSE, &UrlParser);
  if (EFI_ERROR (Status)) {
    goto Error1;
  }

  RequestStr = NULL;
  HostName   = NULL;
  Status     = HttpUrlGetHostName (Url, UrlParser, &HostName);
  if (EFI_ERROR (Status)) {
    goto Error1;
  }

  Status = HttpUrlGetPort (Url, UrlParser, &RemotePort);
  if (EFI_ERROR (Status)) {
    RemotePort = HTTP_DEFAULT_PORT;
  }

  Configure   = TRUE;
  ReConfigure = TRUE;  

  if (HttpInstance->RemoteHost == NULL && HttpInstance->RemotePort == 0) {
    //
    // Request() is called the first time. 
    //
    ReConfigure = FALSE;
  } else {
    if ((HttpInstance->RemotePort == RemotePort) &&
        (AsciiStrCmp (HttpInstance->RemoteHost, HostName) == 0)) {
      //
      // Host Name and port number of the request URL are the same with previous call to Request().
      // Check whether previous TCP packet sent out.
      //
      if (EFI_ERROR (NetMapIterate (&HttpInstance->TxTokens, HttpTcpNotReady, NULL))) {
        //
        // Wrap the HTTP token in HTTP_TOKEN_WRAP
        //
        Wrap = AllocateZeroPool (sizeof (HTTP_TOKEN_WRAP));
        if (Wrap == NULL) {
          Status = EFI_OUT_OF_RESOURCES;
          goto Error1;
        }

        Wrap->HttpToken    = Token;
        Wrap->HttpInstance = HttpInstance;

        Status = HttpCreateTcp4TxEvent (Wrap);
        if (EFI_ERROR (Status)) {
          goto Error1;
        }

        Status = NetMapInsertTail (&HttpInstance->TxTokens, Token, Wrap);
        if (EFI_ERROR (Status)) {
          goto Error1;
        }

        Wrap->TcpWrap.Method = Request->Method;

        FreePool (Url);
        FreePool (HostName);
        
        //
        // Queue the HTTP token and return.
        //
        return EFI_SUCCESS;
      } else {
        //
        // Use existing TCP instance to transmit the packet.
        //
        Configure   = FALSE;
        ReConfigure = FALSE;
      }
    } else {
      //
      // Need close existing TCP instance and create a new TCP instance for data transmit.
      //
      if (HttpInstance->RemoteHost != NULL) {
        FreePool (HttpInstance->RemoteHost);
        HttpInstance->RemoteHost = NULL;
      }
    }
  } 

  if (Configure) {
    //
    // Parse Url for IPv4 address, if failed, perform DNS resolution.
    //
    Status = NetLibAsciiStrToIp4 (HostName, &HttpInstance->RemoteAddr);
    if (EFI_ERROR (Status)) {
      HostNameStr = AllocateZeroPool ((AsciiStrLen (HostName) + 1) * sizeof (UINT16));
      if (HostNameStr == NULL) {
        Status = EFI_OUT_OF_RESOURCES;
        goto Error1;
      }

      AsciiStrToUnicodeStr (HostName, HostNameStr);
      Status = HttpDns4 (HttpInstance, HostNameStr, &HttpInstance->RemoteAddr);
      FreePool (HostNameStr);
      if (EFI_ERROR (Status)) {
        goto Error1;
      }
    }

    //
    // Save the RemotePort and RemoteHost.
    //
    ASSERT (HttpInstance->RemoteHost == NULL);
    HttpInstance->RemotePort = RemotePort;
    HttpInstance->RemoteHost = HostName;
    HostName = NULL;
  }

  if (ReConfigure) {
    //
    // The request URL is different from previous calls to Request(), close existing TCP instance.
    //
    ASSERT (HttpInstance->Tcp4 != NULL);
    HttpCloseConnection (HttpInstance);
    EfiHttpCancel (This, NULL);
  }

  //
  // Wrap the HTTP token in HTTP_TOKEN_WRAP
  //
  Wrap = AllocateZeroPool (sizeof (HTTP_TOKEN_WRAP));
  if (Wrap == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Error1;
  }

  Wrap->HttpToken      = Token;
  Wrap->HttpInstance   = HttpInstance;
  Wrap->TcpWrap.Method = Request->Method;

  if (Configure) {
    //
    // Configure TCP instance.
    //
    Status = HttpConfigureTcp4 (HttpInstance, Wrap);
    if (EFI_ERROR (Status)) {
      goto Error1;
    }
    //
    // Connect TCP.
    //
    Status = HttpConnectTcp4 (HttpInstance);
    if (EFI_ERROR (Status)) {
      goto Error2;
    }
  } else {
    //
    // For the new HTTP token, create TX TCP token events.    
    //
    Status = HttpCreateTcp4TxEvent (Wrap);
    if (EFI_ERROR (Status)) {
      goto Error1;
    }
  }

  //
  // Create request message.
  //
  RequestStr = HttpGenRequestString (HttpInstance, HttpMsg, Url);
  if (RequestStr == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Error3;
  }

  Status = NetMapInsertTail (&HttpInstance->TxTokens, Token, Wrap);
  if (EFI_ERROR (Status)) {
    goto Error4;
  }

  FreePool (Url);
  if (HostName != NULL) {
    FreePool (HostName);
  }

  //
  // Transmit the request message.
  //
  Status = HttpTransmitTcp4 (
             HttpInstance,
             Wrap,
             (UINT8*) RequestStr,
             AsciiStrLen (RequestStr)
             );
  if (EFI_ERROR (Status)) {
    goto Error5;    
  }

  return EFI_SUCCESS;

Error5:
    NetMapRemoveTail (&HttpInstance->TxTokens, NULL);

Error4:
  if (RequestStr != NULL) {
    FreePool (RequestStr);
  }  

Error3:
  HttpCloseConnection (HttpInstance);


Error2:
  HttpCloseTcp4ConnCloseEvent (HttpInstance);
  if (NULL != Wrap->TcpWrap.TxToken.CompletionToken.Event) {
    gBS->CloseEvent (Wrap->TcpWrap.TxToken.CompletionToken.Event);
  }

Error1:
  if (Url != NULL) {
    FreePool (Url);
  }
  if (HostName != NULL) {
    FreePool (HostName);
  }
  if (Wrap != NULL) {
    FreePool (Wrap);
  }
  if (UrlParser!= NULL) {
    HttpUrlFreeParser (UrlParser);
  }

  return Status;
  
}
Esempio n. 29
0
/**
Internal work function to fill in EFI_OPEN_FILE information for the FV

@param  File        Open file handle
@param  FileName    Name of file after device stripped off


**/
EFI_STATUS
EblFvFileDevicePath (
  IN OUT EFI_OPEN_FILE  *File,
  IN  CHAR8             *FileName,
  IN  CONST UINT64      OpenMode
  )
{
  EFI_STATUS                          Status;
  EFI_STATUS                          GetNextFileStatus;
  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH   DevicePathNode;
  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
  UINTN                               Key;
  UINT32                              AuthenticationStatus;
  CHAR8                               AsciiSection[MAX_PATHNAME];
  VOID                                *Section;
  UINTN                               SectionSize;
  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;
  EFI_LBA                             Lba;
  UINTN                               BlockSize;
  UINTN                               NumberOfBlocks;
  EFI_FIRMWARE_VOLUME_HEADER          *FvHeader = NULL;
  UINTN                               Index;


  Status = gBS->HandleProtocol (File->EfiHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&File->Fv);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  // Get FVB Info about the handle
  Status = gBS->HandleProtocol (File->EfiHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);
  if (!EFI_ERROR (Status)) {
    Status = Fvb->GetPhysicalAddress (Fvb, &File->FvStart);
    if (!EFI_ERROR (Status)) {
      FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)File->FvStart;
      File->FvHeaderSize = sizeof (EFI_FIRMWARE_VOLUME_HEADER);
      for (Index = 0; FvHeader->BlockMap[Index].Length !=0; Index++) {
        File->FvHeaderSize += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
      }

      for (Lba = 0, File->FvSize = 0, NumberOfBlocks = 0; ; File->FvSize += (BlockSize * NumberOfBlocks), Lba += NumberOfBlocks) {
        Status = Fvb->GetBlockSize (Fvb, Lba, &BlockSize, &NumberOfBlocks);
        if (EFI_ERROR (Status)) {
          break;
        }
      }
    }
  }


  DevicePath = DevicePathFromHandle (File->EfiHandle);

  if (*FileName == '\0') {
    File->DevicePath = DuplicateDevicePath (DevicePath);
    File->Size = File->FvSize;
    File->MaxPosition = File->Size;
  } else {
    Key = 0;
    do {
      File->FvType = EFI_FV_FILETYPE_ALL;
      GetNextFileStatus = File->Fv->GetNextFile (
        File->Fv,
        &Key,
        &File->FvType,
        &File->FvNameGuid,
        &File->FvAttributes,
        &File->Size
        );
      if (!EFI_ERROR (GetNextFileStatus)) {
        // Compare GUID first
        Status = CompareGuidToString (&File->FvNameGuid, FileName);
        if (!EFI_ERROR(Status)) {
          break;
        }

        Section = NULL;
        Status = File->Fv->ReadSection (
          File->Fv,
          &File->FvNameGuid,
          EFI_SECTION_USER_INTERFACE,
          0,
          &Section,
          &SectionSize,
          &AuthenticationStatus
          );
        if (!EFI_ERROR (Status)) {
          UnicodeStrToAsciiStr (Section, AsciiSection);
          if (AsciiStriCmp (FileName, AsciiSection) == 0) {
            FreePool (Section);
            break;
          }
          FreePool (Section);
        }
      }
    } while (!EFI_ERROR (GetNextFileStatus));

    if (EFI_ERROR (GetNextFileStatus)) {
      return GetNextFileStatus;
    }

    if (OpenMode != EFI_SECTION_ALL) {
      // Calculate the size of the section we are targeting
      Section = NULL;
      File->Size = 0;
      Status = File->Fv->ReadSection (
        File->Fv,
        &File->FvNameGuid,
        (EFI_SECTION_TYPE)OpenMode,
        0,
        &Section,
        &File->Size,
        &AuthenticationStatus
        );
      if (EFI_ERROR (Status)) {
        return Status;
      }
    }

    File->MaxPosition = File->Size;
    EfiInitializeFwVolDevicepathNode (&DevicePathNode, &File->FvNameGuid);
    File->DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&DevicePathNode);
  }


  // FVB not required if FV was soft loaded...
  return EFI_SUCCESS;
}
Esempio n. 30
0
/**
  Open a file on the host system by means of the semihosting interface.

  @param[in]   This        A pointer to the EFI_FILE_PROTOCOL instance that is
                           the file handle to source location.
  @param[out]  NewHandle   A pointer to the location to return the opened
                           handle for the new file.
  @param[in]   FileName    The Null-terminated string of the name of the file
                           to be opened.
  @param[in]   OpenMode    The mode to open the file : Read or Read/Write or
                           Read/Write/Create
  @param[in]   Attributes  Only valid for EFI_FILE_MODE_CREATE, in which case these
                           are the attribute bits for the newly created file. The
                           mnemonics of the attribute bits are : EFI_FILE_READ_ONLY,
                           EFI_FILE_HIDDEN, EFI_FILE_SYSTEM, EFI_FILE_RESERVED,
                           EFI_FILE_DIRECTORY and EFI_FILE_ARCHIVE.

  @retval  EFI_SUCCESS            The file was open.
  @retval  EFI_NOT_FOUND          The specified file could not be found.
  @retval  EFI_DEVICE_ERROR       The last issued semi-hosting operation failed.
  @retval  EFI_WRITE_PROTECTED    Attempt to create a directory. This is not possible
                                  with the semi-hosting interface.
  @retval  EFI_OUT_OF_RESOURCES   Not enough resources were available to open the file.
  @retval  EFI_INVALID_PARAMETER  At least one of the parameters is invalid.

**/
EFI_STATUS
FileOpen (
  IN  EFI_FILE  *This,
  OUT EFI_FILE  **NewHandle,
  IN  CHAR16    *FileName,
  IN  UINT64    OpenMode,
  IN  UINT64    Attributes
  )
{
  SEMIHOST_FCB   *FileFcb;
  RETURN_STATUS  Return;
  EFI_STATUS     Status;
  UINTN          SemihostHandle;
  CHAR8          *AsciiFileName;
  UINT32         SemihostMode;
  UINTN          Length;

  if ((FileName == NULL) || (NewHandle == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  if ( (OpenMode != EFI_FILE_MODE_READ) &&
       (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE)) &&
       (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE)) ) {
    return EFI_INVALID_PARAMETER;
  }

  if ((OpenMode & EFI_FILE_MODE_CREATE) &&
      (Attributes & EFI_FILE_DIRECTORY)    ) {
    return EFI_WRITE_PROTECTED;
  }

  AsciiFileName = AllocatePool (StrLen (FileName) + 1);
  if (AsciiFileName == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  UnicodeStrToAsciiStr (FileName, AsciiFileName);

  // Opening '/', '\', '.', or the NULL pathname is trying to open the root directory
  if ((AsciiStrCmp (AsciiFileName, "\\") == 0) ||
      (AsciiStrCmp (AsciiFileName, "/")  == 0) ||
      (AsciiStrCmp (AsciiFileName, "")   == 0) ||
      (AsciiStrCmp (AsciiFileName, ".")  == 0)    ) {
    FreePool (AsciiFileName);
    return (VolumeOpen (&gSemihostFs, NewHandle));
  }

  //
  // No control is done here concerning the file path. It is passed
  // as it is to the host operating system through the semi-hosting
  // interface. We first try to open the file in the read or update
  // mode even if the file creation has been asked for. That way, if
  // the file already exists, it is not truncated to zero length. In
  // write mode (bit SEMIHOST_FILE_MODE_WRITE up), if the file already
  // exists, it is reset to an empty file.
  //
  if (OpenMode == EFI_FILE_MODE_READ) {
    SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY;
  } else {
    SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY | SEMIHOST_FILE_MODE_UPDATE;
  }
  Return = SemihostFileOpen (AsciiFileName, SemihostMode, &SemihostHandle);

  if (RETURN_ERROR (Return)) {
    if (OpenMode & EFI_FILE_MODE_CREATE) {
      //
      // In the create if does not exist case, if the opening in update
      // mode failed, create it and open it in update mode. The update
      // mode allows for both read and write from and to the file.
      //
      Return = SemihostFileOpen (
                 AsciiFileName,
                 SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY | SEMIHOST_FILE_MODE_UPDATE,
                 &SemihostHandle
                 );
      if (RETURN_ERROR (Return)) {
        Status = EFI_DEVICE_ERROR;
        goto Error;
      }
    } else {
      Status = EFI_NOT_FOUND;
      goto Error;
    }
  }

  // Allocate a control block and fill it
  FileFcb = AllocateFCB ();
  if (FileFcb == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Error;
  }

  FileFcb->FileName       = AsciiFileName;
  FileFcb->SemihostHandle = SemihostHandle;
  FileFcb->Position       = 0;
  FileFcb->IsRoot         = 0;
  FileFcb->OpenMode       = OpenMode;

  Return = SemihostFileLength (SemihostHandle, &Length);
  if (RETURN_ERROR (Return)) {
    Status = EFI_DEVICE_ERROR;
    FreeFCB (FileFcb);
    goto Error;
  }

  FileFcb->Info.FileSize     = Length;
  FileFcb->Info.PhysicalSize = Length;
  FileFcb->Info.Attribute    = (OpenMode & EFI_FILE_MODE_CREATE) ? Attributes : 0;

  InsertTailList (&gFileList, &FileFcb->Link);

  *NewHandle = &FileFcb->File;

  return EFI_SUCCESS;

Error:

  FreePool (AsciiFileName);

  return Status;
}