Esempio n. 1
0
/**
  Writes a buffer to variable storage space, in the working block.

  This function writes a buffer to variable storage space into a firmware
  volume block device. The destination is specified by parameter
  VariableBase. Fault Tolerant Write protocol is used for writing.

  @param  VariableBase   Base address of variable to write
  @param  Buffer         Point to the data buffer.
  @param  BufferSize     The number of bytes of the data Buffer.

  @retval EFI_SUCCESS    The function completed successfully.
  @retval EFI_NOT_FOUND  Fail to locate Fault Tolerant Write protocol.
  @retval EFI_ABORTED    The function could not complete successfully.

**/
EFI_STATUS
FtwVariableSpace (
  IN EFI_PHYSICAL_ADDRESS   VariableBase,
  IN UINT8                  *Buffer,
  IN UINTN                  BufferSize
  )
{
  EFI_STATUS                         Status;
  EFI_HANDLE                         FvbHandle;
  EFI_LBA                            VarLba;
  UINTN                              VarOffset;
  UINT8                              *FtwBuffer;
  UINTN                              FtwBufferSize;
  EFI_FAULT_TOLERANT_WRITE_PROTOCOL  *FtwProtocol;

  //
  // Locate fault tolerant write protocol.
  //
  Status = GetFtwProtocol((VOID **) &FtwProtocol);
  if (EFI_ERROR (Status)) {
    return EFI_NOT_FOUND;
  }
  //
  // Locate Fvb handle by address.
  //
  Status = GetFvbInfoByAddress (VariableBase, &FvbHandle, NULL);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Get LBA and Offset by address.
  //
  Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset);
  if (EFI_ERROR (Status)) {
    return EFI_ABORTED;
  }
  //
  // Prepare for the variable data.
  //
  FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;
  FtwBuffer     = AllocatePool (FtwBufferSize);
  if (FtwBuffer == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  SetMem (FtwBuffer, FtwBufferSize, (UINT8) 0xff);
  CopyMem (FtwBuffer, Buffer, BufferSize);

  //
  // FTW write record.
  //
  Status = FtwProtocol->Write (
                          FtwProtocol,
                          VarLba,         // LBA
                          VarOffset,      // Offset
                          FtwBufferSize,  // NumBytes
                          NULL,           // PrivateData NULL
                          FvbHandle,      // Fvb Handle
                          FtwBuffer       // write buffer
                          );

  FreePool (FtwBuffer);
  return Status;
}
EFI_STATUS
BBTestQueryCapsuleCapabilitiesConformanceTest (
  IN EFI_BB_TEST_PROTOCOL       *This,
  IN VOID                       *ClientInterface,
  IN EFI_TEST_LEVEL             TestLevel,
  IN EFI_HANDLE                 SupportHandle
  )
{
  EFI_STATUS                           Status;
  EFI_STANDARD_TEST_LIBRARY_PROTOCOL   *StandardLib;
  EFI_TEST_ASSERTION                   AssertionType;
  UINT8                                *AllocatedBuffer;
  EFI_CAPSULE_HEADER                  *CapsuleHeaderArray[2];
  EFI_RESET_TYPE                       ResetType;

  //
  // Get the Standard Library Interface
  //
  Status = gtBS->HandleProtocol (
                   SupportHandle,
                   &gEfiStandardTestLibraryGuid,
                   &StandardLib
                   );

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

  if (FALSE == CheckBBTestCanRunAndRecordAssertion(
                  StandardLib, 
                  L"RT.QueryCapsuleCapabilities_Conf - QueryCapsuleCapabilities_Conf it's not Supported in EFI",
                  __FILE__,
                  (UINTN)__LINE__
                  )) {
    return EFI_SUCCESS;
  }

  AllocatedBuffer = (UINT8 *)AllocatePool (sizeof(EFI_CAPSULE_HEADER));
  if (AllocatedBuffer == NULL) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"RT.QueryCapsuleCapabilities_Conf - Allocate zero pool for EFI_CAPSULE_HEADER",
                   L"%a:%d,Status - %r",
                   __FILE__,
                   (UINTN)__LINE__,
                   Status
                   );
    return Status;
  }

  CapsuleHeaderArray[0] = (EFI_CAPSULE_HEADER *) (UINTN)AllocatedBuffer;
  CapsuleHeaderArray[0]->CapsuleGuid = mEfiCapsuleHeaderGuid;
  CapsuleHeaderArray[0]->HeaderSize = sizeof(EFI_CAPSULE_HEADER);
  CapsuleHeaderArray[0]->CapsuleImageSize = sizeof(EFI_CAPSULE_HEADER);
  CapsuleHeaderArray[1] = NULL;
// When the flag is CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE and CAPSULE_FLAGS_PERSIST_ACROSS_RESET, platform will ignore the CapsuleGuid   
  CapsuleHeaderArray[0]->Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE;

  Status = gtRT->QueryCapsuleCapabilities(
  	               CapsuleHeaderArray, 
  	               1, 
  	               NULL, //invalid
  	               &ResetType);
  if ((Status == EFI_INVALID_PARAMETER) || (Status == EFI_UNSUPPORTED)) {
  	AssertionType = EFI_TEST_ASSERTION_PASSED;
  } else {
    AssertionType = EFI_TEST_ASSERTION_FAILED;
  }

  StandardLib->RecordAssertion (
                 StandardLib,
                 AssertionType,
                 gMiscRuntimeServicesBBTestConformanceAssertionGuid004,
                 L"RT.QueryCapsuleCapabilities - invoke QueryCapsuleCapabilities with invalid MaxiumCapsuleSize",
                 L"%a:%d:Status - %r",
                 __FILE__,
                 (UINTN)__LINE__,
                 Status
                 );

  FreePool (AllocatedBuffer);
  return EFI_SUCCESS;
}
Esempio n. 3
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. 4
0
File: Mbr.c Progetto: bayasist/vbox
/**
  Install child handles if the Handle supports MBR format.

  @param[in]  This              Calling context.
  @param[in]  Handle            Parent Handle.
  @param[in]  DiskIo            Parent DiskIo interface.
  @param[in]  BlockIo           Parent BlockIo interface.
  @param[in]  BlockIo2          Parent BlockIo2 interface.
  @param[in]  DevicePath        Parent Device Path.

  @retval EFI_SUCCESS       A child handle was added.
  @retval EFI_MEDIA_CHANGED Media change was detected.
  @retval Others            MBR partition was not found.

**/
EFI_STATUS
PartitionInstallMbrChildHandles (
  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN  EFI_HANDLE                   Handle,
  IN  EFI_DISK_IO_PROTOCOL         *DiskIo,
  IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,
  IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,
  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
  )
{
  EFI_STATUS                Status;
  MASTER_BOOT_RECORD        *Mbr;
  UINT32                    ExtMbrStartingLba;
  UINTN                     Index;
  HARDDRIVE_DEVICE_PATH     HdDev;
  HARDDRIVE_DEVICE_PATH     ParentHdDev;
  EFI_STATUS                Found;
  UINT32                    PartitionNumber;
  EFI_DEVICE_PATH_PROTOCOL  *DevicePathNode;
  EFI_DEVICE_PATH_PROTOCOL  *LastDevicePathNode;
  UINT32                    BlockSize;
  UINT32                    MediaId;
  EFI_LBA                   LastBlock;

  Found           = EFI_NOT_FOUND;

  BlockSize = BlockIo->Media->BlockSize;
  MediaId   = BlockIo->Media->MediaId;
  LastBlock = BlockIo->Media->LastBlock;

  VBoxLogFlowFuncMarkDP(DevicePath);
  Mbr = AllocatePool (BlockSize);
  if (Mbr == NULL) {
    return Found;
  }

  Status = DiskIo->ReadDisk (
                     DiskIo,
                     MediaId,
                     0,
                     BlockSize,
                     Mbr
                     );
  if (EFI_ERROR (Status)) {
    Found = Status;
    goto Done;
  }
  if (!PartitionValidMbr (Mbr, LastBlock)) {
    goto Done;
  }
  //
  // We have a valid mbr - add each partition
  //
  //
  // Get starting and ending LBA of the parent block device.
  //
  LastDevicePathNode = NULL;
  ZeroMem (&ParentHdDev, sizeof (ParentHdDev));
  DevicePathNode = DevicePath;
  while (!IsDevicePathEnd (DevicePathNode)) {
    LastDevicePathNode  = DevicePathNode;
    DevicePathNode      = NextDevicePathNode (DevicePathNode);
  }

  if (LastDevicePathNode != NULL) {
    if (DevicePathType (LastDevicePathNode) == MEDIA_DEVICE_PATH &&
        DevicePathSubType (LastDevicePathNode) == MEDIA_HARDDRIVE_DP
        ) {
      CopyMem (&ParentHdDev, LastDevicePathNode, sizeof (ParentHdDev));
    } else {
      LastDevicePathNode = NULL;
    }
  }

  PartitionNumber = 1;

  ZeroMem (&HdDev, sizeof (HdDev));
  HdDev.Header.Type     = MEDIA_DEVICE_PATH;
  HdDev.Header.SubType  = MEDIA_HARDDRIVE_DP;
  SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev));
  HdDev.MBRType         = MBR_TYPE_PCAT;
  HdDev.SignatureType   = SIGNATURE_TYPE_MBR;

  if (LastDevicePathNode == NULL) {
    //
    // This is a MBR, add each partition
    //
    for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {
      if (Mbr->Partition[Index].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index].SizeInLBA) == 0) {
        //
        // Don't use null MBR entries
        //
        continue;
      }

      if (Mbr->Partition[Index].OSIndicator == PMBR_GPT_PARTITION) {
        //
        // This is the guard MBR for the GPT. If you ever see a GPT disk with zero partitions you can get here.
        //  We can not produce an MBR BlockIo for this device as the MBR spans the GPT headers. So formating
        //  this BlockIo would corrupt the GPT structures and require a recovery that would corrupt the format
        //  that corrupted the GPT partition.
        //
        continue;
      }

      HdDev.PartitionNumber = PartitionNumber ++;
      HdDev.PartitionStart  = UNPACK_UINT32 (Mbr->Partition[Index].StartingLBA);
      HdDev.PartitionSize   = UNPACK_UINT32 (Mbr->Partition[Index].SizeInLBA);
      CopyMem (HdDev.Signature, &(Mbr->UniqueMbrSignature[0]), sizeof (Mbr->UniqueMbrSignature));

      Status = PartitionInstallChildHandle (
                This,
                Handle,
                DiskIo,
                BlockIo,
                BlockIo2,
                DevicePath,
                (EFI_DEVICE_PATH_PROTOCOL *) &HdDev,
                HdDev.PartitionStart,
                HdDev.PartitionStart + HdDev.PartitionSize - 1,
                MBR_SIZE,
                (BOOLEAN) (Mbr->Partition[Index].OSIndicator == EFI_PARTITION)
                );

      if (!EFI_ERROR (Status)) {
        Found = EFI_SUCCESS;
      }
    }
  } else {
    //
    // It's an extended partition. Follow the extended partition
    // chain to get all the logical drives
    //
    ExtMbrStartingLba = 0;

    do {

      Status = DiskIo->ReadDisk (
                         DiskIo,
                         MediaId,
                         MultU64x32 (ExtMbrStartingLba, BlockSize),
                         BlockSize,
                         Mbr
                         );
      if (EFI_ERROR (Status)) {
        Found = Status;
        goto Done;
      }

      if (UNPACK_UINT32 (Mbr->Partition[0].SizeInLBA) == 0) {
        break;
      }

      if ((Mbr->Partition[0].OSIndicator == EXTENDED_DOS_PARTITION) ||
          (Mbr->Partition[0].OSIndicator == EXTENDED_WINDOWS_PARTITION)) {
        ExtMbrStartingLba = UNPACK_UINT32 (Mbr->Partition[0].StartingLBA);
        continue;
      }
      HdDev.PartitionNumber = PartitionNumber ++;
      HdDev.PartitionStart  = UNPACK_UINT32 (Mbr->Partition[0].StartingLBA) + ExtMbrStartingLba + ParentHdDev.PartitionStart;
      HdDev.PartitionSize   = UNPACK_UINT32 (Mbr->Partition[0].SizeInLBA);
      if ((HdDev.PartitionStart + HdDev.PartitionSize - 1 >= ParentHdDev.PartitionStart + ParentHdDev.PartitionSize) ||
          (HdDev.PartitionStart <= ParentHdDev.PartitionStart)) {
        break;
      }

      //
      // The signature in EBR(Extended Boot Record) should always be 0.
      //
      *((UINT32 *) &HdDev.Signature[0]) = 0;

      Status = PartitionInstallChildHandle (
                 This,
                 Handle,
                 DiskIo,
                 BlockIo,
                 BlockIo2,
                 DevicePath,
                 (EFI_DEVICE_PATH_PROTOCOL *) &HdDev,
                 HdDev.PartitionStart - ParentHdDev.PartitionStart,
                 HdDev.PartitionStart - ParentHdDev.PartitionStart + HdDev.PartitionSize - 1,
                 MBR_SIZE,
                 (BOOLEAN) (Mbr->Partition[0].OSIndicator == EFI_PARTITION)
                 );
      if (!EFI_ERROR (Status)) {
        Found = EFI_SUCCESS;
      }

      if ((Mbr->Partition[1].OSIndicator != EXTENDED_DOS_PARTITION) &&
          (Mbr->Partition[1].OSIndicator != EXTENDED_WINDOWS_PARTITION)
          ) {
        break;
      }

      ExtMbrStartingLba = UNPACK_UINT32 (Mbr->Partition[1].StartingLBA);
      //
      // Don't allow partition to be self referencing
      //
      if (ExtMbrStartingLba == 0) {
        break;
      }
    } while (ExtMbrStartingLba  < ParentHdDev.PartitionSize);
  }

Done:
  FreePool (Mbr);

  return Found;
}
Esempio n. 5
0
/**
  Worker function that truncate a file specified by its name to a given size.

  @param[in]  FileName  The Null-terminated string of the name of the file to be opened.
  @param[in]  Size      The target size for the file.

  @retval  EFI_SUCCESS       The file was truncated.
  @retval  EFI_DEVICE_ERROR  The last issued semi-hosting operation failed.

**/
STATIC
EFI_STATUS
TruncateFile (
  IN CHAR8  *FileName,
  IN UINTN   Size
  )
{
  EFI_STATUS     Status;
  RETURN_STATUS  Return;
  UINTN          FileHandle;
  UINT8          *Buffer;
  UINTN          Remaining;
  UINTN          Read;
  UINTN          ToRead;

  Status     = EFI_DEVICE_ERROR;
  FileHandle = 0;
  Buffer     = NULL;

  Return = SemihostFileOpen (
             FileName,
             SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY,
             &FileHandle
             );
  if (RETURN_ERROR (Return)) {
    goto Error;
  }

  Buffer = AllocatePool (Size);
  if (Buffer == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Error;
  }

  Read = 0;
  Remaining = Size;
  while (Remaining > 0) {
    ToRead = Remaining;
    Return = SemihostFileRead (FileHandle, &ToRead, Buffer + Read);
    if (RETURN_ERROR (Return)) {
      goto Error;
    }
    Remaining -= ToRead;
    Read      += ToRead;
  }

  Return = SemihostFileClose (FileHandle);
  FileHandle = 0;
  if (RETURN_ERROR (Return)) {
    goto Error;
  }

  Return = SemihostFileOpen (
             FileName,
             SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY,
             &FileHandle
             );
  if (RETURN_ERROR (Return)) {
    goto Error;
  }

  if (Size > 0) {
    Return = SemihostFileWrite (FileHandle, &Size, Buffer);
    if (RETURN_ERROR (Return)) {
      goto Error;
    }
  }

  Status = EFI_SUCCESS;

Error:

  if (FileHandle != 0) {
    SemihostFileClose (FileHandle);
  }
  if (Buffer != NULL) {
    FreePool (Buffer);
  }

  return (Status);

}
Esempio n. 6
0
/**
  Set or update a HTTP header with the field name and corresponding value.

  @param[in]  HttpIoHeader       Point to the HTTP header holder.
  @param[in]  FieldName          Null terminated string which describes a field name.
  @param[in]  FieldValue         Null terminated string which describes the corresponding field value.

  @retval  EFI_SUCCESS           The HTTP header has been set or updated.
  @retval  EFI_INVALID_PARAMETER Any input parameter is invalid.
  @retval  EFI_OUT_OF_RESOURCES  Insufficient resource to complete the operation.
  @retval  Other                 Unexpected error happened.
  
**/
EFI_STATUS
HttpBootSetHeader (
  IN  HTTP_IO_HEADER       *HttpIoHeader,
  IN  CHAR8                *FieldName,
  IN  CHAR8                *FieldValue
  )
{
  EFI_HTTP_HEADER       *Header;
  UINTN                 StrSize;
  CHAR8                 *NewFieldValue;
  
  if (HttpIoHeader == NULL || FieldName == NULL || FieldValue == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Header = HttpFindHeader (HttpIoHeader->HeaderCount, HttpIoHeader->Headers, FieldName);
  if (Header == NULL) {
    //
    // Add a new header.
    //
    if (HttpIoHeader->HeaderCount >= HttpIoHeader->MaxHeaderCount) {
      return EFI_OUT_OF_RESOURCES;
    }
    Header = &HttpIoHeader->Headers[HttpIoHeader->HeaderCount];

    StrSize = AsciiStrSize (FieldName);
    Header->FieldName = AllocatePool (StrSize);
    if (Header->FieldName == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
    CopyMem (Header->FieldName, FieldName, StrSize);
    Header->FieldName[StrSize -1] = '\0';

    StrSize = AsciiStrSize (FieldValue);
    Header->FieldValue = AllocatePool (StrSize);
    if (Header->FieldValue == NULL) {
      FreePool (Header->FieldName);
      return EFI_OUT_OF_RESOURCES;
    }
    CopyMem (Header->FieldValue, FieldValue, StrSize);
    Header->FieldValue[StrSize -1] = '\0';

    HttpIoHeader->HeaderCount++;
  } else {
    //
    // Update an existing one.
    //
    StrSize = AsciiStrSize (FieldValue);
    NewFieldValue = AllocatePool (StrSize);
    if (NewFieldValue == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
    CopyMem (NewFieldValue, FieldValue, StrSize);
    NewFieldValue[StrSize -1] = '\0';
    
    if (Header->FieldValue != NULL) {
      FreePool (Header->FieldValue);
    }
    Header->FieldValue = NewFieldValue;
  }

  return EFI_SUCCESS;
}
Esempio n. 7
0
EFI_STATUS
BootMenuUpdateBootOption (
  IN LIST_ENTRY *BootOptionsList
  )
{
  EFI_STATUS                    Status;
  BDS_LOAD_OPTION_ENTRY         *BootOptionEntry;
  BDS_LOAD_OPTION               *BootOption;
  BDS_LOAD_OPTION_SUPPORT*      DeviceSupport;
  ARM_BDS_LOADER_ARGUMENTS*     BootArguments;
  CHAR16                        BootDescription[BOOT_DEVICE_DESCRIPTION_MAX];
  CHAR8                         CmdLine[BOOT_DEVICE_OPTION_MAX];
  CHAR16                        UnicodeCmdLine[BOOT_DEVICE_OPTION_MAX];
  EFI_DEVICE_PATH               *DevicePath;
  EFI_DEVICE_PATH               *TempInitrdPath;
  ARM_BDS_LOADER_TYPE           BootType;
  ARM_BDS_LOADER_OPTIONAL_DATA* LoaderOptionalData;
  ARM_BDS_LINUX_ARGUMENTS*      LinuxArguments;
  EFI_DEVICE_PATH               *InitrdPathNodes;
  EFI_DEVICE_PATH               *InitrdPath;
  UINTN                         InitrdSize;
  UINTN                         CmdLineSize;
  BOOLEAN                       InitrdSupport;
  UINT8*                        OptionalData;
  UINTN                         OptionalDataSize;
  BOOLEAN                       IsPrintable;
  BOOLEAN                       IsUnicode;

  DisplayBootOptions (BootOptionsList);
  Status = SelectBootOption (BootOptionsList, UPDATE_BOOT_ENTRY, &BootOptionEntry);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  BootOption = BootOptionEntry->BdsLoadOption;

  // Get the device support for this Boot Option
  Status = BootDeviceGetDeviceSupport (BootOption->FilePathList, &DeviceSupport);
  if (EFI_ERROR(Status)) {
    Print(L"Not possible to retrieve the supported device for the update\n");
    return EFI_UNSUPPORTED;
  }

  Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application or the kernel", &DevicePath);
  if (EFI_ERROR(Status)) {
    Status = EFI_ABORTED;
    goto EXIT;
  }

  if (DeviceSupport->RequestBootType) {
    Status = BootDeviceGetType (DevicePath, &BootType, &BootOption->Attributes);
    if (EFI_ERROR(Status)) {
      Status = EFI_ABORTED;
      goto EXIT;
    }
  }

  LoaderOptionalData = BootOption->OptionalData;
  if (LoaderOptionalData != NULL) {
    BootType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((UINT32 *)(&LoaderOptionalData->Header.LoaderType));
  } else {
    BootType = BDS_LOADER_EFI_APPLICATION;
  }

  if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {
    LinuxArguments = &LoaderOptionalData->Arguments.LinuxArguments;

    CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize);

    InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize);
    if (InitrdSize > 0) {
      Print(L"Keep the initrd: ");
    } else {
      Print(L"Add an initrd: ");
    }
    Status = GetHIInputBoolean (&InitrdSupport);
    if (EFI_ERROR(Status)) {
      Status = EFI_ABORTED;
      goto EXIT;
    }

    if (InitrdSupport) {
      if (InitrdSize > 0) {
        // Case we update the initrd device path
        Status = DeviceSupport->UpdateDevicePathNode ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize), L"initrd", &InitrdPath);
        if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) {// EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd
          Status = EFI_ABORTED;
          goto EXIT;
        }
        InitrdSize = GetDevicePathSize (InitrdPath);
      } else {
        // Case we create the initrd device path

        Status = DeviceSupport->CreateDevicePathNode (L"initrd", &InitrdPathNodes);
        if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd
          Status = EFI_ABORTED;
          goto EXIT;
        }

        if (InitrdPathNodes != NULL) {
          // Duplicate Linux kernel Device Path
          TempInitrdPath = DuplicateDevicePath (BootOption->FilePathList);
          // Replace Linux kernel Node by EndNode
          SetDevicePathEndNode (GetLastDevicePathNode (TempInitrdPath));
          // Append the Device Path to the selected device path
          InitrdPath = AppendDevicePath (TempInitrdPath, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes);
          FreePool (TempInitrdPath);
          // Free the InitrdPathNodes created by Support->CreateDevicePathNode()
          FreePool (InitrdPathNodes);
          if (InitrdPath == NULL) {
            Status = EFI_OUT_OF_RESOURCES;
            goto EXIT;
          }
          InitrdSize = GetDevicePathSize (InitrdPath);
        } else {
          InitrdPath = NULL;
        }
      }
    } else {
      InitrdSize = 0;
    }

    Print(L"Arguments to pass to the binary: ");
    if (CmdLineSize > 0) {
      AsciiStrnCpy (CmdLine, (CONST CHAR8*)(LinuxArguments + 1), sizeof (CmdLine));
      CmdLine[sizeof (CmdLine) - 1] = '\0';
    } else {
      CmdLine[0] = '\0';
    }
    Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX);
    if (EFI_ERROR(Status)) {
      Status = EFI_ABORTED;
      goto FREE_DEVICE_PATH;
    }

    CmdLineSize = AsciiStrSize (CmdLine);

    OptionalDataSize = sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize;
    BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (OptionalDataSize);
    BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;
    BootArguments->LinuxArguments.InitrdSize = InitrdSize;
    CopyMem (&BootArguments->LinuxArguments + 1, CmdLine, CmdLineSize);
    CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);

    OptionalData = (UINT8*)BootArguments;
  } else {
    Print (L"Arguments to pass to the EFI Application: ");

    if (BootOption->OptionalDataSize > 0) {
      IsPrintable = IsPrintableString (BootOption->OptionalData, &IsUnicode);
      if (IsPrintable) {
          //
          // The size in bytes of the string, final zero included, should
          // be equal to or at least lower than "BootOption->OptionalDataSize"
          // and the "IsPrintableString()" has already tested that the length
          // in number of characters is smaller than BOOT_DEVICE_OPTION_MAX,
          // final '\0' included. We can thus copy the string for editing
          // using "CopyMem()". Furthermore, note that in the case of an Unicode
          // string "StrnCpy()" and "StrCpy()" can not be used to copy the
          // string because the data pointed to by "BootOption->OptionalData"
          // is not necessarily 2-byte aligned.
          //
        if (IsUnicode) {
          CopyMem (
            UnicodeCmdLine, BootOption->OptionalData,
            MIN (sizeof (UnicodeCmdLine),
                 BootOption->OptionalDataSize)
            );
        } else {
          CopyMem (
            CmdLine, BootOption->OptionalData,
            MIN (sizeof (CmdLine),
                 BootOption->OptionalDataSize)
            );
        }
      }
    } else {
      UnicodeCmdLine[0] = L'\0';
      IsPrintable = TRUE;
      IsUnicode = TRUE;
    }

    // We do not request arguments for OptionalData that cannot be printed
    if (IsPrintable) {
      if (IsUnicode) {
        Status = EditHIInputStr (UnicodeCmdLine, BOOT_DEVICE_OPTION_MAX);
        if (EFI_ERROR (Status)) {
          Status = EFI_ABORTED;
          goto FREE_DEVICE_PATH;
        }

        OptionalData = (UINT8*)UnicodeCmdLine;
        OptionalDataSize = StrSize (UnicodeCmdLine);
      } else {
        Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX);
        if (EFI_ERROR (Status)) {
          Status = EFI_ABORTED;
          goto FREE_DEVICE_PATH;
        }

        OptionalData = (UINT8*)CmdLine;
        OptionalDataSize = AsciiStrSize (CmdLine);
      }
    } else {
      // We keep the former OptionalData
      OptionalData = BootOption->OptionalData;
      OptionalDataSize = BootOption->OptionalDataSize;
    }
  }

  Print(L"Description for this new Entry: ");
  StrnCpy (BootDescription, BootOption->Description, BOOT_DEVICE_DESCRIPTION_MAX);
  Status = EditHIInputStr (BootDescription, BOOT_DEVICE_DESCRIPTION_MAX);
  if (EFI_ERROR(Status)) {
    Status = EFI_ABORTED;
    goto FREE_DEVICE_PATH;
  }

  // Update the entry
  Status = BootOptionUpdate (BootOption, BootOption->Attributes, BootDescription, DevicePath, BootType, OptionalData, OptionalDataSize);

FREE_DEVICE_PATH:
  FreePool (DevicePath);

EXIT:
  if (Status == EFI_ABORTED) {
    Print(L"\n");
  }
  return Status;
}
//
// TDS 3.4.3
//
EFI_STATUS
DevicePathUtilitiesAppendDevicePathConformanceTest (
  IN EFI_BB_TEST_PROTOCOL       *This,
  IN VOID                       *ClientInterface,
  IN EFI_TEST_LEVEL             TestLevel,
  IN EFI_HANDLE                 SupportHandle
  )
{
  EFI_STANDARD_TEST_LIBRARY_PROTOCOL  *StandardLib;
  EFI_STATUS                          Status;
  EFI_DEVICE_PATH_UTILITIES_PROTOCOL  *DevicePathUtilities;
  EFI_TEST_ASSERTION                  AssertionType;
  EFI_DEVICE_PATH_PROTOCOL            *pDevicePath1;
  EFI_DEVICE_PATH_PROTOCOL            *pDevicePath2;
  EFI_DEVICE_PATH_PROTOCOL            *pDevicePath3;
  EFI_DEVICE_PATH_PROTOCOL            *pDevicePath4;
  UINTN                               DevicePathLen1;
  UINTN                               DevicePathLen2;
  UINTN                               DevicePathLen3;
  //
  // Get the Standard Library Interface
  //
  Status = gtBS->HandleProtocol (
                  SupportHandle,
                  &gEfiStandardTestLibraryGuid,
                  &StandardLib
                  );

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

  DevicePathUtilities = (EFI_DEVICE_PATH_UTILITIES_PROTOCOL *) ClientInterface;

  //
  // TDS 3.4.3.2.1
  //
  pDevicePath1 = (EFI_DEVICE_PATH *) AllocatePool (END_DEVICE_PATH_LENGTH);
  SetDevicePathEndNode (pDevicePath1);

  pDevicePath3  = DevicePathUtilities->CreateDeviceNode (USBNodeType, USBNodeSubType, USBNodeLength);
  pDevicePath4  = DevicePathUtilities->AppendDeviceNode (pDevicePath1, pDevicePath3);
  FreePool (pDevicePath1);
  FreePool (pDevicePath3);
  DevicePathLen2  = DevicePathUtilities->GetDevicePathSize (pDevicePath4);

  pDevicePath1    = DevicePathUtilities->AppendDevicePath (NULL, pDevicePath4);
  FreePool (pDevicePath4);
  DevicePathLen3 = DevicePathUtilities->GetDevicePathSize (pDevicePath1);
  FreePool (pDevicePath1);

  if (DevicePathLen2 == DevicePathLen3) {
    AssertionType = EFI_TEST_ASSERTION_PASSED;
  } else {
    AssertionType = EFI_TEST_ASSERTION_FAILED;
  }

  StandardLib->RecordAssertion (
                StandardLib,
                AssertionType,
                gDevicePathUtilitiesBBTestFunctionAssertionGuid059,
                L"EFI_DEVICE_PATH_UTILITIES_PROTOCOL - AppendDevicePath should ignore Src1 when it is set NULL",
                L"%a:%d:Status - %r",
                __FILE__,
                (UINTN)__LINE__
                );

  //
  // TDS 3.4.3.2.2
  //
  pDevicePath1 = (EFI_DEVICE_PATH *) AllocatePool (END_DEVICE_PATH_LENGTH);
  if (pDevicePath1 == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  SetDevicePathEndNode (pDevicePath1);
  DevicePathLen1  = DevicePathUtilities->GetDevicePathSize (pDevicePath1);

  pDevicePath2    = DevicePathUtilities->CreateDeviceNode (PCIRootNodeType, PCIRootNodeSubType, PCIRootNodeLength);
  pDevicePath3    = DevicePathUtilities->AppendDeviceNode (pDevicePath1, pDevicePath2);
  FreePool (pDevicePath1);
  FreePool (pDevicePath2);

  pDevicePath1  = DevicePathUtilities->CreateDeviceNode (PCINodeType, PCINodeSubType, PCINodeLength);
  pDevicePath2  = DevicePathUtilities->AppendDeviceNode (pDevicePath3, pDevicePath1);
  FreePool (pDevicePath3);
  FreePool (pDevicePath1);
  DevicePathLen1  = DevicePathUtilities->GetDevicePathSize (pDevicePath2);

  pDevicePath1    = DevicePathUtilities->AppendDevicePath (pDevicePath2, NULL);
  FreePool (pDevicePath2);
  DevicePathLen3 = DevicePathUtilities->GetDevicePathSize (pDevicePath1);
  FreePool (pDevicePath1);

  if (DevicePathLen1 == DevicePathLen3) {
    AssertionType = EFI_TEST_ASSERTION_PASSED;
  } else {
    AssertionType = EFI_TEST_ASSERTION_FAILED;
  }

  StandardLib->RecordAssertion (
                StandardLib,
                AssertionType,
                gDevicePathUtilitiesBBTestFunctionAssertionGuid060,
                L"EFI_DEVICE_PATH_UTILITIES_PROTOCOL - AppendDevicePath should ignore Src2 when it is set NULL",
                L"%a:%d:Status - %r",
                __FILE__,
                (UINTN)__LINE__
                );

  pDevicePath1    = DevicePathUtilities->AppendDevicePath (NULL, NULL);
  if ((pDevicePath1 != NULL) && (IsDevicePathEnd(pDevicePath1))) {
    AssertionType = EFI_TEST_ASSERTION_PASSED;
  } else {
    AssertionType = EFI_TEST_ASSERTION_FAILED;
  }

  StandardLib->RecordAssertion (
                StandardLib,
                AssertionType,
                gDevicePathUtilitiesBBTestFunctionAssertionGuid068,
                L"EFI_DEVICE_PATH_UTILITIES_PROTOCOL - AppendDevicePath should return end-of-device-path if both Src1 and Src2 are NULL",
                L"%a:%d",
                __FILE__,
                (UINTN)__LINE__
                );

  return EFI_SUCCESS;
}
//
// TDS 3.4.4
//
EFI_STATUS
DevicePathUtilitiesAppendDevicePathInstanceConformanceTest (
  IN EFI_BB_TEST_PROTOCOL       *This,
  IN VOID                       *ClientInterface,
  IN EFI_TEST_LEVEL             TestLevel,
  IN EFI_HANDLE                 SupportHandle
  )
{
  EFI_STANDARD_TEST_LIBRARY_PROTOCOL  *StandardLib;
  EFI_STATUS                          Status;
  EFI_DEVICE_PATH_UTILITIES_PROTOCOL  *DevicePathUtilities;
  EFI_TEST_ASSERTION                  AssertionType;
  EFI_DEVICE_PATH_PROTOCOL            *pDevicePath1;
  EFI_DEVICE_PATH_PROTOCOL            *pDevicePath2;
  EFI_DEVICE_PATH_PROTOCOL            *pDevicePath3;

  //
  // Get the Standard Library Interface
  //
  Status = gtBS->HandleProtocol (
                  SupportHandle,
                  &gEfiStandardTestLibraryGuid,
                  &StandardLib
                  );

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

  DevicePathUtilities = (EFI_DEVICE_PATH_UTILITIES_PROTOCOL *) ClientInterface;

  //
  // TDS 3.4.4.2.1
  //
  pDevicePath1 = (EFI_DEVICE_PATH *) AllocatePool (END_DEVICE_PATH_LENGTH);
  if (pDevicePath1 == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  SetDevicePathEndNode (pDevicePath1);

  pDevicePath2  = DevicePathUtilities->CreateDeviceNode (PCIRootNodeType, PCIRootNodeSubType, PCIRootNodeLength);
  pDevicePath3  = DevicePathUtilities->AppendDeviceNode (pDevicePath1, pDevicePath2);
  FreePool (pDevicePath1);
  FreePool (pDevicePath2);

  pDevicePath1  = DevicePathUtilities->CreateDeviceNode (PCINodeType, PCINodeSubType, PCINodeLength);
  pDevicePath2  = DevicePathUtilities->AppendDeviceNode (pDevicePath3, pDevicePath1);
  FreePool (pDevicePath3);
  FreePool (pDevicePath1);

  pDevicePath1 = DevicePathUtilities->AppendDevicePathInstance (pDevicePath2, NULL);
  FreePool (pDevicePath2);

  if (pDevicePath1 == NULL) {
    AssertionType = EFI_TEST_ASSERTION_PASSED;
  } else {
    AssertionType = EFI_TEST_ASSERTION_FAILED;
  }

  StandardLib->RecordAssertion (
                StandardLib,
                AssertionType,
                gDevicePathUtilitiesBBTestFunctionAssertionGuid062,
                L"EFI_DEVICE_PATH_UTILITIES_PROTOCOL - AppendDevicePathInstance should not succeed with DevicePathInstance set to be NULL",
                L"%a:%d:Status - %r",
                __FILE__,
                (UINTN)__LINE__
                );

  return EFI_SUCCESS;
}
Esempio n. 10
0
/**
  Digests the Payload and store the result into the OutData.

  This function calls relevant Hash interface from CryptoLib according to
  the input alogrithm ID. It computes all datas from InDataFragment and output
  the result into the OutData buffer. If the OutDataSize is larger than the related
  Hash alogrithm output size, return EFI_INVALID_PARAMETER.

  @param[in]      AlgorithmId     The authentication Identification.
  @param[in]      InDataFragment  A list contains all data to be authenticated.
  @param[in]      FragmentCount   The size of the InDataFragment.
  @param[out]     OutData         For in, the buffer to receive the output data.
                                  For out, the buffer contains the authenticated data.
  @param[in]      OutDataSize     The size of the buffer of OutData.

  @retval EFI_UNSUPPORTED       If the AuthAlg is not in the support list.
  @retval EFI_SUCCESS           Authenticated the payload successfully.
  @retval EFI_INVALID_PARAMETER If the OutDataSize is larger than the related Hash
                                algorithm could handle.
  @retval otherwise             Authentication of the payload failed.

**/
EFI_STATUS
IpSecCryptoIoHash (
  IN     CONST UINT8              AlgorithmId,
  IN           HASH_DATA_FRAGMENT *InDataFragment,
  IN           UINTN              FragmentCount,
     OUT       UINT8              *OutData,
  IN           UINTN              OutDataSize
  )
{
  UINTN        ContextSize;
  UINTN        Index;
  UINT8        FragmentIndex;
  UINT8        *HashContext;
  EFI_STATUS   Status;
  UINT8        *OutHashData;
  UINTN        OutHashSize;

  Status      = EFI_UNSUPPORTED;
  OutHashData = NULL;

  OutHashSize = IpSecGetHmacDigestLength (AlgorithmId);
  //
  // If the expected hash data size is larger than the related Hash algorithm
  // output length, return EFI_INVALID_PARAMETER.
  //
  if (OutDataSize > OutHashSize) {
    return EFI_INVALID_PARAMETER;
  }
  OutHashData = AllocatePool (OutHashSize);
  if (OutHashData == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  switch (AlgorithmId) {

  case IKE_AALG_NONE:
  case IKE_AALG_NULL:
    return EFI_SUCCESS;

  case IKE_AALG_SHA1HMAC:
    Index = IpSecGetIndexFromAuthList (AlgorithmId);
    if (Index == -1) {
      return Status;
    }
    //
    // Get Context Size
    //
    ContextSize = mIpsecHashAlgorithmList[Index].HashGetContextSize();
    HashContext = AllocateZeroPool (ContextSize);
    if (HashContext == NULL) {
      Status = EFI_OUT_OF_RESOURCES;
      goto Exit;
    }

    //
    // Initiate Hash context and hash the input data.
    //
    if (mIpsecHashAlgorithmList[Index].HashInitiate(HashContext)) {
      for (FragmentIndex = 0; FragmentIndex < FragmentCount; FragmentIndex++) {
        if (!mIpsecHashAlgorithmList[Index].HashUpdate (
                HashContext,
                InDataFragment[FragmentIndex].Data,
                InDataFragment[FragmentIndex].DataSize
                )
          ) {
          goto Exit;
        }
      }
      if (mIpsecHashAlgorithmList[Index].HashFinal (HashContext, OutHashData)) {
        //
        // In some cases, like the Icv computing, the Icv size might be less than
        // the key length size, so copy the part of hash data to the OutData.
        //
        CopyMem (OutData, OutHashData, OutDataSize);
        Status = EFI_SUCCESS;
      }

      goto Exit;
    }

  default:
    return Status;
  }

Exit:
  if (HashContext != NULL) {
    FreePool (HashContext);
  }
  if (OutHashData != NULL) {
    FreePool (OutHashData);
  }

  return Status;
}
//
// TDS 3.4.2
//
EFI_STATUS
DevicePathUtilitiesAppendDeviceNodeConformanceTest (
  IN EFI_BB_TEST_PROTOCOL       *This,
  IN VOID                       *ClientInterface,
  IN EFI_TEST_LEVEL             TestLevel,
  IN EFI_HANDLE                 SupportHandle
  )
{
  EFI_STANDARD_TEST_LIBRARY_PROTOCOL  *StandardLib;
  EFI_STATUS                          Status;
  EFI_DEVICE_PATH_UTILITIES_PROTOCOL  *DevicePathUtilities;
  EFI_TEST_ASSERTION                  AssertionType;
  EFI_DEVICE_PATH_PROTOCOL            *pDevicePath1;
  EFI_DEVICE_PATH_PROTOCOL            *pDevicePath2;
  EFI_DEVICE_PATH_PROTOCOL            *pDevicePath3;
  EFI_DEVICE_PATH_PROTOCOL            *pDevicePath4;

  //
  // Get the Standard Library Interface
  //
  Status = gtBS->HandleProtocol (
                  SupportHandle,
                  &gEfiStandardTestLibraryGuid,
                  &StandardLib
                  );

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

  DevicePathUtilities = (EFI_DEVICE_PATH_UTILITIES_PROTOCOL *) ClientInterface;

  //
  // TDS 3.4.2.2.1
  //
  pDevicePath1 = (EFI_DEVICE_PATH *) AllocatePool (END_DEVICE_PATH_LENGTH);
  if (pDevicePath1 == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  SetDevicePathEndNode (pDevicePath1);

  pDevicePath2  = DevicePathUtilities->CreateDeviceNode (PCIRootNodeType, PCIRootNodeSubType, PCIRootNodeLength);
  pDevicePath4  = DevicePathUtilities->AppendDeviceNode (pDevicePath1, pDevicePath2);

  pDevicePath3  = DevicePathUtilities->AppendDeviceNode (NULL, pDevicePath2);
  if ((pDevicePath3 != NULL) && (EfiCompareMem(pDevicePath3, pDevicePath4, DevicePathUtilities->GetDevicePathSize (pDevicePath3)) == 0)) {
    AssertionType = EFI_TEST_ASSERTION_PASSED;
  } else {
    AssertionType = EFI_TEST_ASSERTION_FAILED;
  }

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

  StandardLib->RecordAssertion (
                StandardLib,
                AssertionType,
                gDevicePathUtilitiesBBTestFunctionAssertionGuid054,
                L"EFI_DEVICE_PATH_UTILITIES_PROTOCOL - AppendDeviceNode should return a copy of DeviceNode if DevicePath is NULL",
                L"%a:%d",
                __FILE__,
                (UINTN)__LINE__
                );

  //
  // TDS 3.4.2.2.2
  //
  pDevicePath3 = DevicePathUtilities->AppendDeviceNode (pDevicePath4, NULL);
  if ((pDevicePath3 != NULL) && (EfiCompareMem(pDevicePath3, pDevicePath4, DevicePathUtilities->GetDevicePathSize (pDevicePath3)) == 0)) {
    AssertionType = EFI_TEST_ASSERTION_PASSED;
  } else {
    AssertionType = EFI_TEST_ASSERTION_FAILED;
  }

  if (pDevicePath2 != NULL) {
    FreePool(pDevicePath2);
  }
  if (pDevicePath3 != NULL) {
    FreePool(pDevicePath3);
  }
  if (pDevicePath4 != NULL) {
    FreePool(pDevicePath4);
  }

  StandardLib->RecordAssertion (
                StandardLib,
                AssertionType,
                gDevicePathUtilitiesBBTestFunctionAssertionGuid055,
                L"EFI_DEVICE_PATH_UTILITIES_PROTOCOL - AppendDeviceNode should return a copy of DevicePath if DeviceNode is NULL",
                L"%a:%d",
                __FILE__,
                (UINTN)__LINE__
                );

  pDevicePath3 = DevicePathUtilities->AppendDeviceNode (NULL, NULL);
  if ((pDevicePath3 != NULL) && (EfiCompareMem(pDevicePath3, pDevicePath1, DevicePathUtilities->GetDevicePathSize (pDevicePath3)) == 0)) {
    AssertionType = EFI_TEST_ASSERTION_PASSED;
  } else {
    AssertionType = EFI_TEST_ASSERTION_FAILED;
  }

  FreePool(pDevicePath1);
  if (pDevicePath3 != NULL) {
    FreePool(pDevicePath3);
  }

  StandardLib->RecordAssertion (
                StandardLib,
                AssertionType,
                gDevicePathUtilitiesBBTestFunctionAssertionGuid069,
                L"EFI_DEVICE_PATH_UTILITIES_PROTOCOL - AppendDeviceNode should return end-of-device-path device node if both DevicePath and DeviceNode are NULL",
                L"%a:%d",
                __FILE__,
                (UINTN)__LINE__
                );

  return EFI_SUCCESS;
}
Esempio n. 12
0
/**
  Append a capsule header on top of current image.
  This function follows Windows UEFI Firmware Update Platform document.

  @retval EFI_SUCCESS            The capsule header is appended.
  @retval EFI_UNSUPPORTED        Input parameter is not valid.
  @retval EFI_OUT_OF_RESOURCES   No enough resource to append capsule header.
**/
EFI_STATUS
CreateNestedFmp (
  VOID
  )
{
  CHAR16                                        *OutputCapsuleName;
  VOID                                          *CapsuleBuffer;
  UINTN                                         FileSize;
  CHAR16                                        *CapsuleName;
  UINT8                                         *FullCapsuleBuffer;
  UINTN                                         FullCapsuleBufferSize;
  EFI_CAPSULE_HEADER                            *NestedCapsuleHeader;
  EFI_GUID                                      *ImageTypeId;
  UINT32                                        FwType;
  EFI_STATUS                                    Status;

  if (Argc != 5) {
    Print(L"CapsuleApp: Incorrect parameter count.\n");
    return EFI_UNSUPPORTED;
  }

  if (StrCmp(Argv[3], L"-O") != 0) {
    Print(L"CapsuleApp: NO output capsule name.\n");
    return EFI_UNSUPPORTED;
  }
  OutputCapsuleName = Argv[4];

  CapsuleBuffer = NULL;
  FileSize = 0;
  FullCapsuleBuffer = NULL;

  CapsuleName = Argv[2];
  Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer);
  if (EFI_ERROR(Status)) {
    Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName);
    goto Done;
  }

  ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer);
  if (ImageTypeId == NULL) {
    Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n");
    goto Done;
  }
  FwType = GetEsrtFwType(ImageTypeId);
  if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType != ESRT_FW_TYPE_DEVICEFIRMWARE)) {
    Print(L"CapsuleApp: Capsule FwType is invalid.\n");
    goto Done;
  }

  FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize;
  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
  if (FullCapsuleBuffer == NULL) {
    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n", FullCapsuleBufferSize);
    Status = EFI_OUT_OF_RESOURCES;
    goto Done;
  }

  NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer;
  ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE);
  CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId);
  NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE;
  NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_SYSTEMFIRMWARE) ? SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG;
  NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize;

  CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize, CapsuleBuffer, FileSize);

  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize, FullCapsuleBuffer);
  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);

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

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

  return Status;
}
Esempio n. 13
0
/**
  Create UX capsule.

  @retval EFI_SUCCESS            The capsule header is appended.
  @retval EFI_UNSUPPORTED        Input parameter is not valid.
  @retval EFI_OUT_OF_RESOURCES   No enough resource to create UX capsule.
**/
EFI_STATUS
CreateBmpFmp (
  VOID
  )
{
  CHAR16                                        *OutputCapsuleName;
  VOID                                          *BmpBuffer;
  UINTN                                         FileSize;
  CHAR16                                        *BmpName;
  UINT8                                         *FullCapsuleBuffer;
  UINTN                                         FullCapsuleBufferSize;
  EFI_DISPLAY_CAPSULE                           *DisplayCapsule;
  EFI_STATUS                                    Status;
  EFI_GRAPHICS_OUTPUT_PROTOCOL                  *Gop;
  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION          *Info;
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL                 *GopBlt;
  UINTN                                         GopBltSize;
  UINTN                                         Height;
  UINTN                                         Width;

  Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop);
  if (EFI_ERROR(Status)) {
    Print(L"CapsuleApp: NO GOP is found.\n");
    return EFI_UNSUPPORTED;
  }
  Info = Gop->Mode->Info;
  Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode);
  Print(L"HorizontalResolution - %d, ", Info->HorizontalResolution);
  Print(L"VerticalResolution - %d\n", Info->VerticalResolution);
  // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth
  // VerticalResolution   >= BMP_IMAGE_HEADER.PixelHeight

  if (Argc != 5) {
    Print(L"CapsuleApp: Incorrect parameter count.\n");
    return EFI_UNSUPPORTED;
  }

  if (StrCmp(Argv[3], L"-O") != 0) {
    Print(L"CapsuleApp: NO output capsule name.\n");
    return EFI_UNSUPPORTED;
  }
  OutputCapsuleName = Argv[4];

  BmpBuffer = NULL;
  FileSize = 0;
  FullCapsuleBuffer = NULL;

  BmpName = Argv[2];
  Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer);
  if (EFI_ERROR(Status)) {
    Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName);
    goto Done;
  }

  GopBlt = NULL;
  Status = TranslateBmpToGopBlt (
             BmpBuffer,
             FileSize,
             &GopBlt,
             &GopBltSize,
             &Height,
             &Width
             );
  if (EFI_ERROR(Status)) {
    Print(L"CapsuleApp: BMP image (%s) is not valid.\n", BmpName);
    goto Done;
  }
  if (GopBlt != NULL) {
    FreePool (GopBlt);
  }
  Print(L"BMP image (%s), Width - %d, Height - %d\n", BmpName, Width, Height);

  if (Height > Info->VerticalResolution) {
    Status = EFI_INVALID_PARAMETER;
    Print(L"CapsuleApp: BMP image (%s) height is larger than current resolution.\n", BmpName);
    goto Done;
  }
  if (Width > Info->HorizontalResolution) {
    Status = EFI_INVALID_PARAMETER;
    Print(L"CapsuleApp: BMP image (%s) width is larger than current resolution.\n", BmpName);
    goto Done;
  }

  FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize;
  FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize);
  if (FullCapsuleBuffer == NULL) {
    Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n", FullCapsuleBufferSize);
    Status = EFI_OUT_OF_RESOURCES;
    goto Done;
  }

  DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer;
  CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid);
  DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader);
  DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
  DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize;

  DisplayCapsule->ImagePayload.Version = 1;
  DisplayCapsule->ImagePayload.Checksum = 0;
  DisplayCapsule->ImagePayload.ImageType = 0; // BMP
  DisplayCapsule->ImagePayload.Reserved = 0;
  DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode;

  //
  // Center the bitmap horizontally
  //
  DisplayCapsule->ImagePayload.OffsetX = (UINT32)((Info->HorizontalResolution - Width) / 2);

  //
  // Put bitmap 3/4 down the display.  If bitmap is too tall, then align bottom
  // of bitmap at bottom of display.
  //
  DisplayCapsule->ImagePayload.OffsetY =
    MIN (
      (UINT32)(Info->VerticalResolution - Height),
      (UINT32)(((3 * Info->VerticalResolution) - (2 * Height)) / 4)
      );

  Print(L"BMP image (%s), OffsetX - %d, OffsetY - %d\n",
    BmpName,
    DisplayCapsule->ImagePayload.OffsetX,
    DisplayCapsule->ImagePayload.OffsetY
    );

  CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize);

  DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer, FullCapsuleBufferSize);

  Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize, FullCapsuleBuffer);
  Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status);

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

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

  return Status;
}
Esempio n. 14
0
/**
  Create the Boot####, Driver####, SysPrep####, PlatformRecovery#### variable
  from the load option.

  @param  LoadOption      Pointer to the load option.

  @retval EFI_SUCCESS     The variable was created.
  @retval Others          Error status returned by RT->SetVariable.
**/
EFI_STATUS
EFIAPI
EfiBootManagerLoadOptionToVariable (
  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION     *Option
  )
{
  EFI_STATUS                       Status;
  UINTN                            VariableSize;
  UINT8                            *Variable;
  UINT8                            *Ptr;
  CHAR16                           OptionName[BM_OPTION_NAME_LEN];
  CHAR16                           *Description;
  CHAR16                           NullChar;
  EDKII_VARIABLE_LOCK_PROTOCOL     *VariableLock;
  UINT32                           VariableAttributes;

  if ((Option->OptionNumber == LoadOptionNumberUnassigned) ||
      (Option->FilePath == NULL) ||
      ((UINT32) Option->OptionType >= LoadOptionTypeMax)
     ) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Convert NULL description to empty description
  //
  NullChar    = L'\0';
  Description = Option->Description;
  if (Description == NULL) {
    Description = &NullChar;
  }

  /*
  UINT32                      Attributes;
  UINT16                      FilePathListLength;
  CHAR16                      Description[];
  EFI_DEVICE_PATH_PROTOCOL    FilePathList[];
  UINT8                       OptionalData[];
TODO: FilePathList[] IS:
A packed array of UEFI device paths.  The first element of the
array is a device path that describes the device and location of the
Image for this load option.  The FilePathList[0] is specific
to the device type.  Other device paths may optionally exist in the
FilePathList, but their usage is OSV specific. Each element
in the array is variable length, and ends at the device path end
structure.
  */
  VariableSize = sizeof (Option->Attributes)
               + sizeof (UINT16)
               + StrSize (Description)
               + GetDevicePathSize (Option->FilePath)
               + Option->OptionalDataSize;

  Variable     = AllocatePool (VariableSize);
  ASSERT (Variable != NULL);

  Ptr             = Variable;
  WriteUnaligned32 ((UINT32 *) Ptr, Option->Attributes);
  Ptr            += sizeof (Option->Attributes);

  WriteUnaligned16 ((UINT16 *) Ptr, (UINT16) GetDevicePathSize (Option->FilePath));
  Ptr            += sizeof (UINT16);

  CopyMem (Ptr, Description, StrSize (Description));
  Ptr            += StrSize (Description);

  CopyMem (Ptr, Option->FilePath, GetDevicePathSize (Option->FilePath));
  Ptr            += GetDevicePathSize (Option->FilePath);

  CopyMem (Ptr, Option->OptionalData, Option->OptionalDataSize);

  UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", mBmLoadOptionName[Option->OptionType], Option->OptionNumber);

  VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE;
  if (Option->OptionType == LoadOptionTypePlatformRecovery) {
    //
    // Lock the PlatformRecovery####
    //
    Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);
    if (!EFI_ERROR (Status)) {
      Status = VariableLock->RequestToLock (VariableLock, OptionName, &gEfiGlobalVariableGuid);
      ASSERT_EFI_ERROR (Status);
    }
    VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
  }

  Status = gRT->SetVariable (
                  OptionName,
                  &gEfiGlobalVariableGuid,
                  VariableAttributes,
                  VariableSize,
                  Variable
                  );
  FreePool (Variable);

  return Status;
}
Esempio n. 15
0
File: Gpt.c Progetto: etiago/vbox
/**
  Restore Partition Table to its alternate place
  (Primary -> Backup or Backup -> Primary).

  @param[in]  BlockIo     Parent BlockIo interface.
  @param[in]  DiskIo      Disk Io Protocol.
  @param[in]  PartHeader  Partition table header structure.

  @retval TRUE      Restoring succeeds
  @retval FALSE     Restoring failed

**/
BOOLEAN
PartitionRestoreGptTable (
  IN  EFI_BLOCK_IO_PROTOCOL       *BlockIo,
  IN  EFI_DISK_IO_PROTOCOL        *DiskIo,
  IN  EFI_PARTITION_TABLE_HEADER  *PartHeader
  )
{
  EFI_STATUS                  Status;
  UINTN                       BlockSize;
  EFI_PARTITION_TABLE_HEADER  *PartHdr;
  EFI_LBA                     PEntryLBA;
  UINT8                       *Ptr;
  UINT32                      MediaId;

  PartHdr   = NULL;
  Ptr       = NULL;

  BlockSize = BlockIo->Media->BlockSize;
  MediaId   = BlockIo->Media->MediaId;

  PartHdr   = AllocateZeroPool (BlockSize);

  if (PartHdr == NULL) {
    DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
    return FALSE;
  }

  PEntryLBA = (PartHeader->MyLBA == PRIMARY_PART_HEADER_LBA) ? \
                             (PartHeader->LastUsableLBA + 1) : \
                             (PRIMARY_PART_HEADER_LBA + 1);

  CopyMem (PartHdr, PartHeader, sizeof (EFI_PARTITION_TABLE_HEADER));

  PartHdr->MyLBA              = PartHeader->AlternateLBA;
  PartHdr->AlternateLBA       = PartHeader->MyLBA;
  PartHdr->PartitionEntryLBA  = PEntryLBA;
  PartitionSetCrc ((EFI_TABLE_HEADER *) PartHdr);

  Status = DiskIo->WriteDisk (
                     DiskIo,
                     MediaId,
                     MultU64x32 (PartHdr->MyLBA, (UINT32) BlockSize),
                     BlockSize,
                     PartHdr
                     );
  if (EFI_ERROR (Status)) {
    goto Done;
  }

  Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);
  if (Ptr == NULL) {
    DEBUG ((EFI_D_ERROR, " Allocate pool error\n"));
    Status = EFI_OUT_OF_RESOURCES;
    goto Done;
  }

  Status = DiskIo->ReadDisk (
                    DiskIo,
                    MediaId,
                    MultU64x32(PartHeader->PartitionEntryLBA, (UINT32) BlockSize),
                    PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
                    Ptr
                    );
  if (EFI_ERROR (Status)) {
    goto Done;
  }

  Status = DiskIo->WriteDisk (
                    DiskIo,
                    MediaId,
                    MultU64x32(PEntryLBA, (UINT32) BlockSize),
                    PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
                    Ptr
                    );

Done:
  FreePool (PartHdr);

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

  if (EFI_ERROR (Status)) {
    return FALSE;
  }

  return TRUE;
}
Esempio n. 16
0
EFI_STATUS
EFIAPI
QemuVideoGraphicsOutputSetMode (
  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  IN  UINT32                       ModeNumber
  )
/*++

Routine Description:

  Graphics Output protocol interface to set video mode

  Arguments:
    This             - Protocol instance pointer.
    ModeNumber       - The mode number to be set.

  Returns:
    EFI_SUCCESS      - Graphics mode was changed.
    EFI_DEVICE_ERROR - The device had an error and could not complete the request.
    EFI_UNSUPPORTED  - ModeNumber is not supported by this device.

--*/
{
  QEMU_VIDEO_PRIVATE_DATA    *Private;
  QEMU_VIDEO_MODE_DATA       *ModeData;
//  UINTN                             Count;

  Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);

  if (ModeNumber >= This->Mode->MaxMode) {
    return EFI_UNSUPPORTED;
  }

  ModeData = &Private->ModeData[ModeNumber];

  if (Private->LineBuffer) {
    gBS->FreePool (Private->LineBuffer);
  }

  Private->LineBuffer = AllocatePool (4 * ModeData->HorizontalResolution);
  if (Private->LineBuffer == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  switch (Private->Variant) {
  case QEMU_VIDEO_CIRRUS_5430:
  case QEMU_VIDEO_CIRRUS_5446:
    InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]);
    break;
  case QEMU_VIDEO_BOCHS_MMIO:
  case QEMU_VIDEO_BOCHS:
    InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]);
    break;
  default:
    ASSERT (FALSE);
    gBS->FreePool (Private->LineBuffer);
    Private->LineBuffer = NULL;
    return EFI_DEVICE_ERROR;
  }

  This->Mode->Mode = ModeNumber;
  This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
  This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
  This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);

  QemuVideoCompleteModeData (Private, This->Mode);

  BltLibConfigure (
    (VOID*)(UINTN) This->Mode->FrameBufferBase,
    This->Mode->Info
    );

  return EFI_SUCCESS;
}
Esempio n. 17
0
/**
  Retrieve the host address using the EFI_DNS6_PROTOCOL.

  @param[in]  Private             The pointer to the driver's private data.
  @param[in]  HostName            Pointer to buffer containing hostname.
  @param[out] IpAddress           On output, pointer to buffer containing IPv6 address.

  @retval EFI_SUCCESS             Operation succeeded.
  @retval EFI_DEVICE_ERROR        An unexpected network error occurred.
  @retval Others                  Other errors as indicated.  
**/
EFI_STATUS
HttpBootDns (
  IN     HTTP_BOOT_PRIVATE_DATA   *Private,
  IN     CHAR16                   *HostName,
     OUT EFI_IPv6_ADDRESS         *IpAddress 
  )
{
  EFI_STATUS                      Status;
  EFI_DNS6_PROTOCOL               *Dns6;
  EFI_DNS6_CONFIG_DATA            Dns6ConfigData;
  EFI_DNS6_COMPLETION_TOKEN       Token;
  EFI_HANDLE                      Dns6Handle;
  EFI_IP6_CONFIG_PROTOCOL         *Ip6Config;
  EFI_IPv6_ADDRESS                *DnsServerList;
  UINTN                           DnsServerListCount;
  UINTN                           DataSize;
  BOOLEAN                         IsDone;  
  
  DnsServerList       = NULL;
  DnsServerListCount  = 0;
  Dns6                = NULL;
  Dns6Handle          = NULL;
  ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));
  
  //
  // Get DNS server list from EFI IPv6 Configuration protocol.
  //
  Status = gBS->HandleProtocol (Private->Controller, &gEfiIp6ConfigProtocolGuid, (VOID **) &Ip6Config);
  if (!EFI_ERROR (Status)) {
    //
    // Get the required size.
    //
    DataSize = 0;
    Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL);
    if (Status == EFI_BUFFER_TOO_SMALL) {
      DnsServerList = AllocatePool (DataSize);
      if (DnsServerList == NULL) {
        return EFI_OUT_OF_RESOURCES;
      }  

      Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);
      if (EFI_ERROR (Status)) {
        FreePool (DnsServerList);
        DnsServerList = NULL;
      } else {
        DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
      }
    }
  }
  //
  // Create a DNSv6 child instance and get the protocol.
  //
  Status = NetLibCreateServiceChild (
             Private->Controller,
             Private->Ip6Nic->ImageHandle,
             &gEfiDns6ServiceBindingProtocolGuid,
             &Dns6Handle
             );
  if (EFI_ERROR (Status)) {
    goto Exit;
  } 
  
  Status = gBS->OpenProtocol (
                  Dns6Handle,
                  &gEfiDns6ProtocolGuid,
                  (VOID **) &Dns6,
                  Private->Ip6Nic->ImageHandle,
                  Private->Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto Exit;
  }

  //
  // Configure DNS6 instance for the DNS server address and protocol.
  //
  ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));
  Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount;
  Dns6ConfigData.DnsServerList  = DnsServerList;
  Dns6ConfigData.EnableDnsCache = TRUE;
  Dns6ConfigData.Protocol       = EFI_IP_PROTO_UDP;
  IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp,&Private->StationIp.v6);
  Status = Dns6->Configure (
                    Dns6,
                    &Dns6ConfigData
                    );
  if (EFI_ERROR (Status)) {
    goto Exit;
  }
  
  Token.Status = EFI_NOT_READY;
  IsDone       = FALSE;
  //
  // Create event to set the  IsDone flag when name resolution is finished.
  //
  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  HttpBootCommonNotify,
                  &IsDone,
                  &Token.Event
                  );
  if (EFI_ERROR (Status)) {
    goto Exit;
  }

  //
  // Start asynchronous name resolution.
  //
  Status = Dns6->HostNameToIp (Dns6, HostName, &Token);
  if (EFI_ERROR (Status)) {
    goto Exit;
  }

  while (!IsDone) {
    Dns6->Poll (Dns6);
  }
  
  //
  // Name resolution is done, check result.
  //
  Status = Token.Status;  
  if (!EFI_ERROR (Status)) {
    if (Token.RspData.H2AData == NULL) {
      Status = EFI_DEVICE_ERROR;
      goto Exit;
    }
    if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {
      Status = EFI_DEVICE_ERROR;
      goto Exit;
    }
    //
    // We just return the first IPv6 address from DNS protocol.
    //
    IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);
    Status = EFI_SUCCESS;
  }
Exit:

  if (Token.Event != NULL) {
    gBS->CloseEvent (Token.Event);
  }
  if (Token.RspData.H2AData != NULL) {
    if (Token.RspData.H2AData->IpList != NULL) {
      FreePool (Token.RspData.H2AData->IpList);
    }
    FreePool (Token.RspData.H2AData);
  }

  if (Dns6 != NULL) {
    Dns6->Configure (Dns6, NULL);
    
    gBS->CloseProtocol (
           Dns6Handle,
           &gEfiDns6ProtocolGuid,
           Private->Ip6Nic->ImageHandle,
           Private->Controller
           );
  }

  if (Dns6Handle != NULL) {
    NetLibDestroyServiceChild (
      Private->Controller,
      Private->Ip6Nic->ImageHandle,
      &gEfiDns6ServiceBindingProtocolGuid,
      Dns6Handle
      );
  }

  if (DnsServerList != NULL) {
    FreePool (DnsServerList);
  }
  
  return Status;  
}
Esempio n. 18
0
EFI_STATUS
UtilIterateVariables (
  IN VARIABLE_ITERATION_CALLBACK CallbackFunction,
  IN VOID                        *Context
)
{
  RETURN_STATUS               Status;
  UINTN                       VariableNameBufferSize;
  UINTN                       VariableNameSize;
  CHAR16                      *VariableName;
  EFI_GUID                    VendorGuid;
  UINTN                       VariableDataBufferSize;
  UINTN                       VariableDataSize;
  VOID                        *VariableData;
  UINT32                      VariableAttributes;
  VOID                        *NewBuffer;

  //
  // Initialize the variable name and data buffer variables.
  //
  VariableNameBufferSize = sizeof (CHAR16);
  VariableName = AllocateZeroPool (VariableNameBufferSize);

  VariableDataBufferSize = 0;
  VariableData = NULL;

  for (;;) {
    //
    // Get the next variable name and guid
    //
    VariableNameSize = VariableNameBufferSize;
    Status = gRT->GetNextVariableName (
                    &VariableNameSize,
                    VariableName,
                    &VendorGuid
                    );
    if (Status == EFI_BUFFER_TOO_SMALL) {
      //
      // The currently allocated VariableName buffer is too small,
      // so we allocate a larger buffer, and copy the old buffer
      // to it.
      //
      NewBuffer = AllocatePool (VariableNameSize);
      if (NewBuffer == NULL) {
        Status = EFI_OUT_OF_RESOURCES;
        break;
      }
      CopyMem (NewBuffer, VariableName, VariableNameBufferSize);
      if (VariableName != NULL) {
        FreePool (VariableName);
      }
      VariableName = NewBuffer;
      VariableNameBufferSize = VariableNameSize;

      //
      // Try to get the next variable name again with the larger buffer.
      //
      Status = gRT->GetNextVariableName (
                      &VariableNameSize,
                      VariableName,
                      &VendorGuid
                      );
    }

    if (EFI_ERROR (Status)) {
      if (Status == EFI_NOT_FOUND) {
        Status = EFI_SUCCESS;
      }
      break;
    }

    //
    // Get the variable data and attributes
    //
    VariableDataSize = VariableDataBufferSize;
    Status = gRT->GetVariable (
                    VariableName,
                    &VendorGuid,
                    &VariableAttributes,
                    &VariableDataSize,
                    VariableData
                    );
    if (Status == EFI_BUFFER_TOO_SMALL) {
      //
      // The currently allocated VariableData buffer is too small,
      // so we allocate a larger buffer.
      //
      if (VariableDataBufferSize != 0) {
        FreePool (VariableData);
        VariableData = NULL;
        VariableDataBufferSize = 0;
      }
      VariableData = AllocatePool (VariableDataSize);
      if (VariableData == NULL) {
        Status = EFI_OUT_OF_RESOURCES;
        break;
      }
      VariableDataBufferSize = VariableDataSize;

      //
      // Try to read the variable again with the larger buffer.
      //
      Status = gRT->GetVariable (
                      VariableName,
                      &VendorGuid,
                      &VariableAttributes,
                      &VariableDataSize,
                      VariableData
                      );
    }
    if (EFI_ERROR (Status)) {
      break;
    }

    //
    // Run the callback function
    //
    Status = (*CallbackFunction) (
               Context,
               VariableName,
               &VendorGuid,
               VariableAttributes,
               VariableDataSize,
               VariableData
               );
    if (EFI_ERROR (Status)) {
      break;
    }
  }

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

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

  return Status;
}
Esempio n. 19
0
EFI_STATUS
BootMenuAddBootOption (
  IN LIST_ENTRY *BootOptionsList
  )
{
  EFI_STATUS                Status;
  BDS_SUPPORTED_DEVICE*     SupportedBootDevice;
  ARM_BDS_LOADER_ARGUMENTS* BootArguments;
  CHAR16                    BootDescription[BOOT_DEVICE_DESCRIPTION_MAX];
  CHAR8                     AsciiCmdLine[BOOT_DEVICE_OPTION_MAX];
  CHAR16                    CmdLine[BOOT_DEVICE_OPTION_MAX];
  UINT32                    Attributes;
  ARM_BDS_LOADER_TYPE       BootType;
  BDS_LOAD_OPTION_ENTRY     *BdsLoadOptionEntry;
  EFI_DEVICE_PATH           *DevicePath;
  EFI_DEVICE_PATH_PROTOCOL  *DevicePathNodes;
  EFI_DEVICE_PATH_PROTOCOL  *InitrdPathNodes;
  EFI_DEVICE_PATH_PROTOCOL  *InitrdPath;
  UINTN                     CmdLineSize;
  BOOLEAN                   InitrdSupport;
  UINTN                     InitrdSize;
  UINT8*                    OptionalData;
  UINTN                     OptionalDataSize;

  Attributes                = 0;
  SupportedBootDevice = NULL;

  // List the Boot Devices supported
  Status = SelectBootDevice (&SupportedBootDevice);
  if (EFI_ERROR(Status)) {
    Status = EFI_ABORTED;
    goto EXIT;
  }

  // Create the specific device path node
  Status = SupportedBootDevice->Support->CreateDevicePathNode (L"EFI Application or the kernel", &DevicePathNodes);
  if (EFI_ERROR(Status)) {
    Status = EFI_ABORTED;
    goto EXIT;
  }
  // Append the Device Path to the selected device path
  DevicePath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)DevicePathNodes);
  if (DevicePath == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto EXIT;
  }

  if (SupportedBootDevice->Support->RequestBootType) {
    Status = BootDeviceGetType (DevicePath, &BootType, &Attributes);
    if (EFI_ERROR(Status)) {
      Status = EFI_ABORTED;
      goto EXIT;
    }
  } else {
    BootType = BDS_LOADER_EFI_APPLICATION;
  }

  if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {
    Print(L"Add an initrd: ");
    Status = GetHIInputBoolean (&InitrdSupport);
    if (EFI_ERROR(Status)) {
      Status = EFI_ABORTED;
      goto EXIT;
    }

    if (InitrdSupport) {
      // Create the specific device path node
      Status = SupportedBootDevice->Support->CreateDevicePathNode (L"initrd", &InitrdPathNodes);
      if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd
        Status = EFI_ABORTED;
        goto EXIT;
      }

      if (InitrdPathNodes != NULL) {
        // Append the Device Path to the selected device path
        InitrdPath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes);
        // Free the InitrdPathNodes created by Support->CreateDevicePathNode()
        FreePool (InitrdPathNodes);

        if (InitrdPath == NULL) {
          Status = EFI_OUT_OF_RESOURCES;
          goto EXIT;
        }
      } else {
        InitrdPath = NULL;
      }
    } else {
      InitrdPath = NULL;
    }

    Print(L"Arguments to pass to the binary: ");
    Status = GetHIInputAscii (AsciiCmdLine, BOOT_DEVICE_OPTION_MAX);
    if (EFI_ERROR(Status)) {
      Status = EFI_ABORTED;
      goto FREE_DEVICE_PATH;
    }

    CmdLineSize = AsciiStrSize (AsciiCmdLine);
    InitrdSize = GetDevicePathSize (InitrdPath);

    OptionalDataSize = sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize;
    BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (OptionalDataSize);

    BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;
    BootArguments->LinuxArguments.InitrdSize = InitrdSize;
    CopyMem ((VOID*)(&BootArguments->LinuxArguments + 1), AsciiCmdLine, CmdLineSize);
    CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);

    OptionalData = (UINT8*)BootArguments;
  } else {
    Print (L"Arguments to pass to the EFI Application: ");
    Status = GetHIInputStr (CmdLine, BOOT_DEVICE_OPTION_MAX);
    if (EFI_ERROR (Status)) {
      Status = EFI_ABORTED;
      goto EXIT;
    }

    OptionalData = (UINT8*)CmdLine;
    OptionalDataSize = StrSize (CmdLine);
  }

  Print(L"Description for this new Entry: ");
  Status = GetHIInputStr (BootDescription, BOOT_DEVICE_DESCRIPTION_MAX);
  if (EFI_ERROR(Status)) {
    Status = EFI_ABORTED;
    goto FREE_DEVICE_PATH;
  }

  // Create new entry
  BdsLoadOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool (sizeof(BDS_LOAD_OPTION_ENTRY));
  Status = BootOptionCreate (Attributes, BootDescription, DevicePath, BootType, OptionalData, OptionalDataSize, &BdsLoadOptionEntry->BdsLoadOption);
  if (!EFI_ERROR(Status)) {
    InsertTailList (BootOptionsList, &BdsLoadOptionEntry->Link);
  }

FREE_DEVICE_PATH:
  FreePool (DevicePath);

EXIT:
  if (Status == EFI_ABORTED) {
    Print(L"\n");
  }
  FreePool(SupportedBootDevice);
  return Status;
}
Esempio n. 20
0
/**
  Install child handles if the Handle supports El Torito format.

  @param[in]  This        Calling context.
  @param[in]  Handle      Parent Handle.
  @param[in]  DiskIo      Parent DiskIo interface.
  @param[in]  BlockIo     Parent BlockIo interface.
  @param[in]  BlockIo2    Parent BlockIo2 interface.
  @param[in]  DevicePath  Parent Device Path


  @retval EFI_SUCCESS         Child handle(s) was added.
  @retval EFI_MEDIA_CHANGED   Media changed Detected.
  @retval other               no child handle was added.

**/
EFI_STATUS
PartitionInstallElToritoChildHandles (
  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN  EFI_HANDLE                   Handle,
  IN  EFI_DISK_IO_PROTOCOL         *DiskIo,
  IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,
  IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,
  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
  )
{
  EFI_STATUS              Status;
  UINT32                  VolDescriptorLba;
  UINT32                  Lba;
  EFI_BLOCK_IO_MEDIA      *Media;
  CDROM_VOLUME_DESCRIPTOR *VolDescriptor;
  ELTORITO_CATALOG        *Catalog;
  UINTN                   Check;
  UINTN                   Index;
  UINTN                   BootEntry;
  UINTN                   MaxIndex;
  UINT16                  *CheckBuffer;
  CDROM_DEVICE_PATH       CdDev;
  UINT32                  SubBlockSize;
  UINT32                  SectorCount;
  EFI_STATUS              Found;
  UINT32                  VolSpaceSize;

#ifdef VBOX
  VBoxLogFlowFuncMarkDP(DevicePath);
#endif
  Found         = EFI_NOT_FOUND;
  Media         = BlockIo->Media;

  VolSpaceSize  = 0;

  //
  // CD_ROM has the fixed block size as 2048 bytes
  //
  if (Media->BlockSize != 2048) {
    return EFI_NOT_FOUND;
  }

  VolDescriptor = AllocatePool ((UINTN) Media->BlockSize);

  if (VolDescriptor == NULL) {
    return EFI_NOT_FOUND;
  }

  Catalog = (ELTORITO_CATALOG *) VolDescriptor;

  //
  // the ISO-9660 volume descriptor starts at 32k on the media
  // and CD_ROM has the fixed block size as 2048 bytes, so...
  //
  //
  // ((16*2048) / Media->BlockSize) - 1;
  //
  VolDescriptorLba = 15;
  //
  // Loop: handle one volume descriptor per time
  //
  while (TRUE) {

    VolDescriptorLba += 1;
    if (VolDescriptorLba > Media->LastBlock) {
      //
      // We are pointing past the end of the device so exit
      //
      break;
    }

    Status = DiskIo->ReadDisk (
                       DiskIo,
                       Media->MediaId,
                       MultU64x32 (VolDescriptorLba, Media->BlockSize),
                       Media->BlockSize,
                       VolDescriptor
                       );
    if (EFI_ERROR (Status)) {
      Found = Status;
      break;
    }
    //
    // Check for valid volume descriptor signature
    //
    if (VolDescriptor->Unknown.Type == CDVOL_TYPE_END ||
        CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0
        ) {
      //
      // end of Volume descriptor list
      //
      break;
    }
    //
    // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte,
    // the 32-bit numerical values is stored in Both-byte orders
    //
    if (VolDescriptor->PrimaryVolume.Type == CDVOL_TYPE_CODED) {
      VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[0];
    }
    //
    // Is it an El Torito volume descriptor?
    //
    if (CompareMem (VolDescriptor->BootRecordVolume.SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1) != 0) {
      continue;
    }
    //
    // Read in the boot El Torito boot catalog
    //
    Lba = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog);
    if (Lba > Media->LastBlock) {
      continue;
    }

    Status = DiskIo->ReadDisk (
                       DiskIo,
                       Media->MediaId,
                       MultU64x32 (Lba, Media->BlockSize),
                       Media->BlockSize,
                       Catalog
                       );
    if (EFI_ERROR (Status)) {
      DEBUG ((EFI_D_ERROR, "EltCheckDevice: error reading catalog %r\n", Status));
      continue;
    }
    //
    // We don't care too much about the Catalog header's contents, but we do want
    // to make sure it looks like a Catalog header
    //
    if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {
      DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n"));
      continue;
    }

    Check       = 0;
    CheckBuffer = (UINT16 *) Catalog;
    for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {
      Check += CheckBuffer[Index];
    }

    if ((Check & 0xFFFF) != 0) {
      DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));
      continue;
    }

    MaxIndex = Media->BlockSize / sizeof (ELTORITO_CATALOG);
    for (Index = 1, BootEntry = 1; Index < MaxIndex; Index += 1) {
      //
      // Next entry
      //
      Catalog += 1;

      //
      // Check this entry
      //
      if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {
        continue;
      }

      SubBlockSize  = 512;
      SectorCount   = Catalog->Boot.SectorCount;

      switch (Catalog->Boot.MediaType) {

      case ELTORITO_NO_EMULATION:
        SubBlockSize = Media->BlockSize;
        break;

      case ELTORITO_HARD_DISK:
        break;

      case ELTORITO_12_DISKETTE:
        SectorCount = 0x50 * 0x02 * 0x0F;
        break;

      case ELTORITO_14_DISKETTE:
        SectorCount = 0x50 * 0x02 * 0x12;
        break;

      case ELTORITO_28_DISKETTE:
        SectorCount = 0x50 * 0x02 * 0x24;
        break;

      default:
        DEBUG ((EFI_D_INIT, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog->Boot.MediaType));
        SectorCount   = 0;
        SubBlockSize  = Media->BlockSize;
        break;
      }
      //
      // Create child device handle
      //
      CdDev.Header.Type     = MEDIA_DEVICE_PATH;
      CdDev.Header.SubType  = MEDIA_CDROM_DP;
      SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev));

      if (Index == 1) {
        //
        // This is the initial/default entry
        //
        BootEntry = 0;
      }

      CdDev.BootEntry = (UINT32) BootEntry;
      BootEntry++;
      CdDev.PartitionStart = Catalog->Boot.Lba;
      if (SectorCount < 2) {
        //
        // When the SectorCount < 2, set the Partition as the whole CD.
        //
        if (VolSpaceSize > (Media->LastBlock + 1)) {
          CdDev.PartitionSize = (UINT32)(Media->LastBlock - Catalog->Boot.Lba + 1);
        } else {
          CdDev.PartitionSize = (UINT32)(VolSpaceSize - Catalog->Boot.Lba);
        }
      } else {
        CdDev.PartitionSize = DivU64x32 (
                                MultU64x32 (
                                  SectorCount,
                                  SubBlockSize
                                  ) + Media->BlockSize - 1,
                                Media->BlockSize
                                );
      }

      Status = PartitionInstallChildHandle (
                This,
                Handle,
                DiskIo,
                BlockIo,
                BlockIo2,
                DevicePath,
                (EFI_DEVICE_PATH_PROTOCOL *) &CdDev,
                Catalog->Boot.Lba,
                Catalog->Boot.Lba + CdDev.PartitionSize - 1,
                SubBlockSize,
                FALSE
                );
      if (!EFI_ERROR (Status)) {
        Found = EFI_SUCCESS;
      }
    }
  }

  FreePool (VolDescriptor);

  return Found;
}
Esempio n. 21
0
void
console_print_box_at(CHAR16 *str_arr[], int highlight, int start_col, int start_row, int size_cols, int size_rows, int offset, int lines)
{
	int i;
	SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
	UINTN rows, cols;
	CHAR16 *Line;

	if (lines == 0)
		return;

	uefi_call_wrapper(co->QueryMode, 4, co, co->Mode->Mode, &cols, &rows);

	/* last row on screen is unusable without scrolling, so ignore it */
	rows--;

	if (size_rows < 0)
		size_rows = rows + size_rows + 1;
	if (size_cols < 0)
		size_cols = cols + size_cols + 1;

	if (start_col < 0)
		start_col = (cols + start_col + 2)/2;
	if (start_row < 0)
		start_row = (rows + start_row + 2)/2;
	if (start_col < 0)
		start_col = 0;
	if (start_row < 0)
		start_row = 0;

	if (start_col > cols || start_row > rows) {
		Print(L"Starting Position (%d,%d) is off screen\n",
		      start_col, start_row);
		return;
	}
	if (size_cols + start_col > cols)
		size_cols = cols - start_col;
	if (size_rows + start_row > rows)
		size_rows = rows - start_row;
	       
	if (lines > size_rows - 2)
		lines = size_rows - 2;

	Line = AllocatePool((size_cols+1)*sizeof(CHAR16));
	if (!Line) {
		Print(L"Failed Allocation\n");
		return;
	}

	SetMem16 (Line, size_cols * 2, BOXDRAW_HORIZONTAL);

	Line[0] = BOXDRAW_DOWN_RIGHT;
	Line[size_cols - 1] = BOXDRAW_DOWN_LEFT;
	Line[size_cols] = L'\0';
	uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, start_row);
	uefi_call_wrapper(co->OutputString, 2, co, Line);

	int start;
	if (offset == 0)
		/* middle */
		start = (size_rows - lines)/2 + start_row + offset;
	else if (offset < 0)
		/* from bottom */
		start = start_row + size_rows - lines + offset - 1;
	else
		/* from top */
		start = start_row + offset;
		
	for (i = start_row + 1; i < size_rows + start_row - 1; i++) {
		int line = i - start;

		SetMem16 (Line, size_cols*2, L' ');
		Line[0] = BOXDRAW_VERTICAL;
		Line[size_cols - 1] = BOXDRAW_VERTICAL;
		Line[size_cols] = L'\0';
		if (line >= 0 && line < lines) {
			CHAR16 *s = str_arr[line];
			int len = StrLen(s);
			int col = (size_cols - 2 - len)/2;

			if (col < 0)
				col = 0;

			CopyMem(Line + col + 1, s, min(len, size_cols - 2)*2);
		}
		if (line >= 0 && line == highlight) 
			uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK);
		uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, i);
		uefi_call_wrapper(co->OutputString, 2, co, Line);
		if (line >= 0 && line == highlight) 
			uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);

	}
	SetMem16 (Line, size_cols * 2, BOXDRAW_HORIZONTAL);
	Line[0] = BOXDRAW_UP_RIGHT;
	Line[size_cols - 1] = BOXDRAW_UP_LEFT;
	Line[size_cols] = L'\0';
	uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, i);
	uefi_call_wrapper(co->OutputString, 2, co, Line);

	FreePool (Line);

}
Esempio n. 22
0
EFI_STATUS
EblGetCmd (
  IN UINTN  Argc,
  IN CHAR8  **Argv
  )
{
  EFI_STATUS        Status = EFI_INVALID_PARAMETER;
  UINTN       Size;
  VOID*       Value;
  CHAR8*      AsciiVariableName = NULL;
  CHAR16*     VariableName;
  UINT32      Index;

  if (Argc == 1) {
    AsciiPrint("Variable name is missing.\n");
    return Status;
  }

  for (Index = 1; Index < Argc; Index++) {
    if (Argv[Index][0] == '-') {
      AsciiPrint("Warning: '%a' not recognized.\n",Argv[Index]);
    } else {
      AsciiVariableName = Argv[Index];
    }
  }

  if (AsciiVariableName == NULL) {
    AsciiPrint("Variable name is missing.\n");
    return Status;
  } else {
    VariableName = AllocatePool((AsciiStrLen (AsciiVariableName) + 1) * sizeof (CHAR16));
    AsciiStrToUnicodeStr (AsciiVariableName,VariableName);
  }

  // Try to get the variable size.
  Value = NULL;
  Size = 0;
  Status = gRT->GetVariable (VariableName, &gEfiGlobalVariableGuid, NULL, &Size, Value);
  if (Status == EFI_NOT_FOUND) {
    AsciiPrint("Variable name '%s' not found.\n",VariableName);
  } else if (Status == EFI_BUFFER_TOO_SMALL) {
    // Get the environment variable value
    Value = AllocatePool (Size);
    if (Value == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }

    Status = gRT->GetVariable ((CHAR16 *)VariableName, &gEfiGlobalVariableGuid, NULL, &Size, Value);
    if (EFI_ERROR (Status)) {
      AsciiPrint("Error: '%r'\n",Status);
    } else {
      AsciiPrint("%a=%a\n",AsciiVariableName,Value);
    }
    FreePool(Value);
  } else {
    AsciiPrint("Error: '%r'\n",Status);
  }

  FreePool(VariableName);
  return Status;
}
Esempio n. 23
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;
}
Esempio n. 24
0
EFI_STATUS
EblSetCmd (
  IN UINTN  Argc,
  IN CHAR8  **Argv
  )
{
  EFI_STATUS    Status = EFI_INVALID_PARAMETER;
  CHAR8*        AsciiVariableSetting = NULL;
  CHAR8*        AsciiVariableName;
  CHAR8*        AsciiValue;
  UINT32        AsciiValueLength;
  CHAR16*       VariableName;
  UINT32        Index;
  UINT32        EscapedQuotes = 0;
  BOOLEAN       Volatile = FALSE;

  if (Argc == 1) {
    AsciiPrint("Variable name is missing.\n");
    return Status;
  }

  for (Index = 1; Index < Argc; Index++) {
    if (AsciiStrCmp(Argv[Index],"-v") == 0) {
      Volatile = 0;
    } else if (Argv[Index][0] == '-') {
      AsciiPrint("Warning: '%a' not recognized.\n",Argv[Index]);
    } else {
      AsciiVariableSetting = Argv[Index];
    }
  }

  if (AsciiVariableSetting == NULL) {
    AsciiPrint("Variable name is missing.\n");
    return Status;
  }
  
  // Check if it is a valid variable setting
  AsciiValue = AsciiStrStr (AsciiVariableSetting,"=");
  if (AsciiValue == NULL) {
    //
    // There is no value. It means this variable will be deleted
    //

    // Convert VariableName into Unicode
    VariableName = AllocatePool((AsciiStrLen (AsciiVariableSetting) + 1) * sizeof (CHAR16));
    AsciiStrToUnicodeStr (AsciiVariableSetting,VariableName);

    Status = gRT->SetVariable (
                          VariableName,
                          &gEfiGlobalVariableGuid,
                          ( !Volatile ? EFI_VARIABLE_NON_VOLATILE : 0) |
                          EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                          0,
                          NULL
                          );
    if (!EFI_ERROR(Status)) {
      AsciiPrint("Variable '%s' deleted\n",VariableName);
    } else {
      AsciiPrint("Variable setting is incorrect. It should be VariableName=Value\n");
    }
    return Status;
  }

  AsciiValue[0] = '\0';
  AsciiVariableName = AsciiVariableSetting;
  AsciiValue++;

  // Clean AsciiValue from quote
  if (AsciiValue[0] == '"') {
    AsciiValue++;
  }
  AsciiValueLength = AsciiStrLen (AsciiValue);
  if ((AsciiValue[AsciiValueLength-2] != '\\') && (AsciiValue[AsciiValueLength-1] == '"')) {
    AsciiValue[AsciiValueLength-1] = '\0';
  }

  // Clean AsciiValue from escaped quotes
  for (Index = 0; Index < AsciiValueLength; Index++) {
    if ((Index > 0) && (AsciiValue[Index-1] == '\\') && (AsciiValue[Index] == '"')) {
      EscapedQuotes++;
    }
    AsciiValue[Index-EscapedQuotes] = AsciiValue[Index];
  }
  // Fill the end of the value with '\0'
  for (Index = 0; Index < EscapedQuotes; Index++) {
    AsciiValue[AsciiValueLength-1-Index] = '\0';
  }

  // Convert VariableName into Unicode
  VariableName = AllocatePool((AsciiStrLen (AsciiVariableName) + 1) * sizeof (CHAR16));
  AsciiStrToUnicodeStr (AsciiVariableName,VariableName);

  Status = gRT->SetVariable (
                      VariableName,
                      &gEfiGlobalVariableGuid,
                      ( !Volatile ? EFI_VARIABLE_NON_VOLATILE : 0) |
                      EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                      AsciiStrLen (AsciiValue)+1,
                      AsciiValue
                      );
  if (!EFI_ERROR(Status)) {
    AsciiPrint("'%a'='%a'\n",AsciiVariableName,AsciiValue);
  }

  return Status;
}
Esempio n. 25
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. 26
0
/**
  Install child handles if the Handle supports Apple partition table format.

  @param[in]  This        Calling context.
  @param[in]  Handle      Parent Handle
  @param[in]  DiskIo      Parent DiskIo interface
  @param[in]  BlockIo     Parent BlockIo interface
  @param[in]  DevicePath  Parent Device Path


  @retval EFI_SUCCESS         Child handle(s) was added
  @retval EFI_MEDIA_CHANGED   Media changed Detected
  @retval other               no child handle was added

**/
EFI_STATUS
PartitionInstallAppleChildHandles (
  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN  EFI_HANDLE                   Handle,
  IN  EFI_DISK_IO_PROTOCOL         *DiskIo,
  IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,
  IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,
  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
  )
{
  EFI_STATUS                Status;
  UINT32                    Lba;
  EFI_BLOCK_IO_MEDIA       *Media;
  VOID                     *Block;
  //UINTN                   MaxIndex;
  /** @todo: wrong, as this PT can be on both HDD or CD */
  CDROM_DEVICE_PATH         CdDev;
  //EFI_DEVICE_PATH_PROTOCOL  Dev;
  EFI_STATUS                Found;
  UINT32                    Partition;
  UINT32                    PartitionEntries;
  UINT32                    VolSpaceSize;
  UINT32                    SubBlockSize;
  UINT32                    BlkPerSec;

  VBoxLogFlowFuncMarkDP(DevicePath);
  Found         = EFI_NOT_FOUND;
  Media         = BlockIo->Media;
  VolSpaceSize  = 0;

  Block = AllocatePool ((UINTN) Media->BlockSize);

  if (Block == NULL) {
    return EFI_NOT_FOUND;
  }

  do {
      APPLE_PT_HEADER * Header;

      /* read PT header first */
      Lba = 0;

      Status = DiskIo->ReadDisk (
                       DiskIo,
                       Media->MediaId,
                       MultU64x32 (Lba, Media->BlockSize),
                       Media->BlockSize,
                       Block
                       );
      if (EFI_ERROR (Status))
      {
          Found = Status;
          break;
      }

      Header = (APPLE_PT_HEADER *)Block;
      if (be16_to_cpu(Header->sbSig) != 0x4552)
      {
          break;
      }
      SubBlockSize = be16_to_cpu(Header->sbBlkSize);
      BlkPerSec    = Media->BlockSize / SubBlockSize;

      /* Fail if media block size isn't an exact multiple */
      if (Media->BlockSize != SubBlockSize * BlkPerSec)
      {
          break;
      }

      /* Now iterate over PT entries and install child handles */
      PartitionEntries = 1;
      for (Partition = 1; Partition <= PartitionEntries; Partition++)
      {
          APPLE_PT_ENTRY * Entry;
          UINT32 StartLba;
          UINT32 SizeLbs;

          Status = DiskIo->ReadDisk (
                       DiskIo,
                       Media->MediaId,
                       MultU64x32 (Partition, SubBlockSize),
                       SubBlockSize,
                       Block
                       );

          if (EFI_ERROR (Status)) {
              Status = EFI_NOT_FOUND;
              goto done; /* would break, but ... */
          }

          Entry = (APPLE_PT_ENTRY *)Block;

          if (be16_to_cpu(Entry->signature) != 0x504D)
          {
              Print(L"Not a new PT entry: %x", Entry->signature);
              continue;
          }

          /* First partition contains partitions count */
          if (Partition == 1)
          {
             PartitionEntries  = be32_to_cpu(Entry->map_entries);
          }

          StartLba = be32_to_cpu(Entry->pblock_start);
          SizeLbs  = be32_to_cpu(Entry->pblocks);

          if (0 && CompareMem("Apple_HFS", Entry->type, 10) == 0)
              Print(L"HFS partition (%d of %d) at LBA 0x%x size=%dM\n",
                    Partition, PartitionEntries, StartLba,
                    (UINT32)(MultU64x32(SizeLbs, SubBlockSize) / (1024 * 1024)));

          ZeroMem (&CdDev, sizeof (CdDev));
          CdDev.Header.Type     = MEDIA_DEVICE_PATH;
          CdDev.Header.SubType  = MEDIA_CDROM_DP;
          SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev));

          CdDev.BootEntry = 0;
          /* Convert from partition to media blocks */
          CdDev.PartitionStart = StartLba / BlkPerSec;  /* start, LBA */
          CdDev.PartitionSize  = SizeLbs / BlkPerSec;   /* size,  LBs */

          Status = PartitionInstallChildHandle (
              This,
              Handle,
              DiskIo,
              BlockIo,
              BlockIo2,
              DevicePath,
              (EFI_DEVICE_PATH_PROTOCOL *) &CdDev,
              CdDev.PartitionStart,
              CdDev.PartitionStart + CdDev.PartitionSize - 1,
              SubBlockSize,
              FALSE);

          if (!EFI_ERROR (Status)) {
              Found = EFI_SUCCESS;
          }
      }

  } while (0);

 done:
  FreePool (Block);

  return Found;
}
EFI_STATUS
BBTestUpdateCapsuleConformanceTest (
  IN EFI_BB_TEST_PROTOCOL       *This,
  IN VOID                       *ClientInterface,
  IN EFI_TEST_LEVEL             TestLevel,
  IN EFI_HANDLE                 SupportHandle
  )
{
  EFI_STATUS                           Status;
  EFI_STANDARD_TEST_LIBRARY_PROTOCOL   *StandardLib;
  EFI_TEST_ASSERTION                   AssertionType;
  UINT8                                *AllocatedBuffer;
  EFI_CAPSULE_HEADER                  *CapsuleHeaderArray[2];

  //
  // Get the Standard Library Interface
  //
  Status = gtBS->HandleProtocol (
                   SupportHandle,
                   &gEfiStandardTestLibraryGuid,
                   &StandardLib
                   );

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

  if (FALSE == CheckBBTestCanRunAndRecordAssertion (
                  StandardLib, 
                  L"RT.UpdateCapsule_Conf- UpdateCapsule_Conf it's not Supported in EFI",
                  __FILE__,
                  (UINTN)__LINE__
                  )) {
    return EFI_SUCCESS;
  }

  AllocatedBuffer = (UINT8 *)AllocatePool (sizeof(EFI_CAPSULE_HEADER));
  if (EFI_ERROR(Status)) {
    StandardLib->RecordAssertion (
                   StandardLib,
                   EFI_TEST_ASSERTION_FAILED,
                   gTestGenericFailureGuid,
                   L"RT.UpdateCapsule_conf - Allocate pages for EFI_CAPSULE_HEADER",
                   L"%a:%d,Status - %r",
                   __FILE__,
                   (UINTN)__LINE__,
                   Status
                   );
    return Status;
  }

  CapsuleHeaderArray[0] = (EFI_CAPSULE_HEADER *) (UINTN)AllocatedBuffer;
  CapsuleHeaderArray[0]->CapsuleGuid = mEfiCapsuleHeaderGuid;
  CapsuleHeaderArray[0]->HeaderSize = sizeof(EFI_CAPSULE_HEADER);
  CapsuleHeaderArray[0]->CapsuleImageSize = sizeof(EFI_CAPSULE_HEADER);
  CapsuleHeaderArray[1] = NULL;
  CapsuleHeaderArray[0]->Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;


  // When CapsuleCount is 0, the return status code should be EFI_INVALID_PARAMETER
  Status = gtRT->UpdateCapsule(
  	             CapsuleHeaderArray,
  	             0, // invaild
  	             (EFI_PHYSICAL_ADDRESS ) 0
  	             );
  if (Status == EFI_INVALID_PARAMETER) {
  	AssertionType = EFI_TEST_ASSERTION_PASSED;
  } else {
    AssertionType = EFI_TEST_ASSERTION_FAILED;
  }

  StandardLib->RecordAssertion (
                 StandardLib,
                 AssertionType,
                 gMiscRuntimeServicesBBTestConformanceAssertionGuid001,
                 L"RT.UpdateCapsule - invoke UpdateCapsule with invalid CapsuleCount - 0",
                 L"%a:%d:Status - %r",
                 __FILE__,
                 __LINE__,
                 Status
                 );
                
  //
  // when the flag is CAPSULE_FLAGS_PERSIST_ACROSS_RESET, ScatterGatherList can't be NULL.
  //

  CapsuleHeaderArray[0] = (EFI_CAPSULE_HEADER *) (UINTN)AllocatedBuffer;
  CapsuleHeaderArray[0]->CapsuleGuid = mEfiCapsuleHeaderGuid;
  CapsuleHeaderArray[0]->HeaderSize = sizeof(EFI_CAPSULE_HEADER);
  CapsuleHeaderArray[0]->CapsuleImageSize = sizeof(EFI_CAPSULE_HEADER);
  CapsuleHeaderArray[1] = NULL;
  CapsuleHeaderArray[0]->Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE;

  Status = gtRT->UpdateCapsule(
  	             CapsuleHeaderArray,
  	             1,
  	             (EFI_PHYSICAL_ADDRESS ) 0
  	             );
  if (Status == EFI_INVALID_PARAMETER) {
  	AssertionType = EFI_TEST_ASSERTION_PASSED;
  } else {
    AssertionType = EFI_TEST_ASSERTION_FAILED;
  }

  StandardLib->RecordAssertion (
                 StandardLib,
                 AssertionType,
                 gMiscRuntimeServicesBBTestConformanceAssertionGuid002,
                 L"RT.UpdateCapsule - invoke UpdateCapsule with invalid ScatterGatherList",
                 L"%a:%d:Status - %r",
                 __FILE__,
                 __LINE__,
                 Status
                 );


  //
  // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag must have
  // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
  //
  CapsuleHeaderArray[0] = (EFI_CAPSULE_HEADER *) (UINTN)AllocatedBuffer;
  CapsuleHeaderArray[0]->CapsuleGuid = mEfiCapsuleHeaderGuid;
  CapsuleHeaderArray[0]->HeaderSize = sizeof(EFI_CAPSULE_HEADER);
  CapsuleHeaderArray[0]->CapsuleImageSize = sizeof(EFI_CAPSULE_HEADER);
  CapsuleHeaderArray[1] = NULL;
  CapsuleHeaderArray[0]->Flags = CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE;

  Status = gtRT->UpdateCapsule(
  	             CapsuleHeaderArray,
  	             1,
  	             (EFI_PHYSICAL_ADDRESS ) 0
  	             );
  if (Status == EFI_INVALID_PARAMETER) {
  	AssertionType = EFI_TEST_ASSERTION_PASSED;
  } else {
    AssertionType = EFI_TEST_ASSERTION_FAILED;
  }

  StandardLib->RecordAssertion (
                 StandardLib,
                 AssertionType,
                 gMiscRuntimeServicesBBTestConformanceAssertionGuid003,
                 L"RT.UpdateCapsule - invoke UpdateCapsule with invalid Flags",
                 L"%a:%d:Status - %r",
                 __FILE__,
                 (UINTN)__LINE__,
                 Status
                 );
  //
  // A capsule which has the CAPSULE_FLAGS_INITIATE_RESET Flag must have 
  // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
  //
  CapsuleHeaderArray[0] = (EFI_CAPSULE_HEADER *) (UINTN)AllocatedBuffer;
  CapsuleHeaderArray[0]->CapsuleGuid = mEfiCapsuleHeaderGuid;
  CapsuleHeaderArray[0]->HeaderSize = sizeof(EFI_CAPSULE_HEADER);
  CapsuleHeaderArray[0]->CapsuleImageSize = sizeof(EFI_CAPSULE_HEADER);
  CapsuleHeaderArray[1] = NULL;
  CapsuleHeaderArray[0]->Flags = CAPSULE_FLAGS_INITIATE_RESET;

  Status = gtRT->UpdateCapsule(
  	             CapsuleHeaderArray,
  	             1,
  	             (EFI_PHYSICAL_ADDRESS ) 0
  	             );
  if (Status == EFI_INVALID_PARAMETER) {
  	AssertionType = EFI_TEST_ASSERTION_PASSED;
  } else {
    AssertionType = EFI_TEST_ASSERTION_FAILED;
  }

  StandardLib->RecordAssertion (
                 StandardLib,
                 AssertionType,
                 gMiscRuntimeServicesBBTestConformanceAssertionGuid005,
                 L"RT.UpdateCapsule - invoke UpdateCapsule with invalid Flags",
                 L"%a:%d:Status - %r",
                 __FILE__,
                 (UINTN)__LINE__,
                 Status
                 );


  FreePool(AllocatedBuffer);
  return EFI_SUCCESS;
}
Esempio n. 28
0
File: Gpt.c Progetto: etiago/vbox
/**
  Install child handles if the Handle supports GPT partition structure.

  @param[in]  This       Calling context.
  @param[in]  Handle     Parent Handle.
  @param[in]  DiskIo     Parent DiskIo interface.
  @param[in]  BlockIo    Parent BlockIo interface.
  @param[in]  BlockIo2   Parent BlockIo2 interface.
  @param[in]  DevicePath Parent Device Path.

  @retval EFI_SUCCESS           Valid GPT disk.
  @retval EFI_MEDIA_CHANGED     Media changed Detected.
  @retval other                 Not a valid GPT disk.

**/
EFI_STATUS
PartitionInstallGptChildHandles (
  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN  EFI_HANDLE                   Handle,
  IN  EFI_DISK_IO_PROTOCOL         *DiskIo,
  IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,
  IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,
  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
  )
{
  EFI_STATUS                  Status;
  UINT32                      BlockSize;
  EFI_LBA                     LastBlock;
  MASTER_BOOT_RECORD          *ProtectiveMbr;
  EFI_PARTITION_TABLE_HEADER  *PrimaryHeader;
  EFI_PARTITION_TABLE_HEADER  *BackupHeader;
  EFI_PARTITION_ENTRY         *PartEntry;
  EFI_PARTITION_ENTRY         *Entry;
  EFI_PARTITION_ENTRY_STATUS  *PEntryStatus;
  UINTN                       Index;
  EFI_STATUS                  GptValidStatus;
  HARDDRIVE_DEVICE_PATH       HdDev;
  UINT32                      MediaId;

  VBoxLogFlowFuncMarkDP(DevicePath);
  ProtectiveMbr = NULL;
  PrimaryHeader = NULL;
  BackupHeader  = NULL;
  PartEntry     = NULL;
  PEntryStatus  = NULL;

  BlockSize     = BlockIo->Media->BlockSize;
  LastBlock     = BlockIo->Media->LastBlock;
  MediaId       = BlockIo->Media->MediaId;

  DEBUG ((EFI_D_INFO, " BlockSize : %d \n", BlockSize));
  DEBUG ((EFI_D_INFO, " LastBlock : %lx \n", LastBlock));

  GptValidStatus = EFI_NOT_FOUND;

  //
  // Allocate a buffer for the Protective MBR
  //
  ProtectiveMbr = AllocatePool (BlockSize);
  if (ProtectiveMbr == NULL) {
    return EFI_NOT_FOUND;
  }

  //
  // Read the Protective MBR from LBA #0
  //
  Status = DiskIo->ReadDisk (
                     DiskIo,
                     MediaId,
                     0,
                     BlockSize,
                     ProtectiveMbr
                     );
  if (EFI_ERROR (Status)) {
    GptValidStatus = Status;
    goto Done;
  }

  //
  // Verify that the Protective MBR is valid
  //
  for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {
    if (ProtectiveMbr->Partition[Index].BootIndicator == 0x00 &&
        ProtectiveMbr->Partition[Index].OSIndicator == PMBR_GPT_PARTITION &&
        UNPACK_UINT32 (ProtectiveMbr->Partition[Index].StartingLBA) == 1
        ) {
      break;
    }
  }
  if (Index == MAX_MBR_PARTITIONS) {
    goto Done;
  }

  //
  // Allocate the GPT structures
  //
  PrimaryHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER));
  if (PrimaryHeader == NULL) {
    goto Done;
  }

  BackupHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER));
  if (BackupHeader == NULL) {
    goto Done;
  }

  //
  // Check primary and backup partition tables
  //
  if (!PartitionValidGptTable (BlockIo, DiskIo, PRIMARY_PART_HEADER_LBA, PrimaryHeader)) {
    DEBUG ((EFI_D_INFO, " Not Valid primary partition table\n"));

    if (!PartitionValidGptTable (BlockIo, DiskIo, LastBlock, BackupHeader)) {
      DEBUG ((EFI_D_INFO, " Not Valid backup partition table\n"));
      goto Done;
    } else {
      DEBUG ((EFI_D_INFO, " Valid backup partition table\n"));
      DEBUG ((EFI_D_INFO, " Restore primary partition table by the backup\n"));
      if (!PartitionRestoreGptTable (BlockIo, DiskIo, BackupHeader)) {
        DEBUG ((EFI_D_INFO, " Restore primary partition table error\n"));
      }

      if (PartitionValidGptTable (BlockIo, DiskIo, BackupHeader->AlternateLBA, PrimaryHeader)) {
        DEBUG ((EFI_D_INFO, " Restore backup partition table success\n"));
      }
    }
  } else if (!PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) {
    DEBUG ((EFI_D_INFO, " Valid primary and !Valid backup partition table\n"));
    DEBUG ((EFI_D_INFO, " Restore backup partition table by the primary\n"));
    if (!PartitionRestoreGptTable (BlockIo, DiskIo, PrimaryHeader)) {
      DEBUG ((EFI_D_INFO, " Restore  backup partition table error\n"));
    }

    if (PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) {
      DEBUG ((EFI_D_INFO, " Restore backup partition table success\n"));
    }

  }

  DEBUG ((EFI_D_INFO, " Valid primary and Valid backup partition table\n"));

  //
  // Read the EFI Partition Entries
  //
  PartEntry = AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry);
  if (PartEntry == NULL) {
    DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
    goto Done;
  }

  Status = DiskIo->ReadDisk (
                     DiskIo,
                     MediaId,
                     MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockSize),
                     PrimaryHeader->NumberOfPartitionEntries * (PrimaryHeader->SizeOfPartitionEntry),
                     PartEntry
                     );
  if (EFI_ERROR (Status)) {
    GptValidStatus = Status;
    DEBUG ((EFI_D_ERROR, " Partition Entry ReadDisk error\n"));
    goto Done;
  }

  DEBUG ((EFI_D_INFO, " Partition entries read block success\n"));

  DEBUG ((EFI_D_INFO, " Number of partition entries: %d\n", PrimaryHeader->NumberOfPartitionEntries));

  PEntryStatus = AllocateZeroPool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY_STATUS));
  if (PEntryStatus == NULL) {
    DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
    goto Done;
  }

  //
  // Check the integrity of partition entries
  //
  PartitionCheckGptEntry (PrimaryHeader, PartEntry, PEntryStatus);

  //
  // If we got this far the GPT layout of the disk is valid and we should return true
  //
  GptValidStatus = EFI_SUCCESS;

  //
  // Create child device handles
  //
  for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {
    Entry = (EFI_PARTITION_ENTRY *) ((UINT8 *) PartEntry + Index * PrimaryHeader->SizeOfPartitionEntry);
    if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid) ||
        PEntryStatus[Index].OutOfRange ||
        PEntryStatus[Index].Overlap ||
        PEntryStatus[Index].OsSpecific
        ) {
      //
      // Don't use null EFI Partition Entries, Invalid Partition Entries or OS specific
      // partition Entries
      //
      continue;
    }

    ZeroMem (&HdDev, sizeof (HdDev));
    HdDev.Header.Type     = MEDIA_DEVICE_PATH;
    HdDev.Header.SubType  = MEDIA_HARDDRIVE_DP;
    SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev));

    HdDev.PartitionNumber = (UINT32) Index + 1;
    HdDev.MBRType         = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;
    HdDev.SignatureType   = SIGNATURE_TYPE_GUID;
    HdDev.PartitionStart  = Entry->StartingLBA;
    HdDev.PartitionSize   = Entry->EndingLBA - Entry->StartingLBA + 1;
    CopyMem (HdDev.Signature, &Entry->UniquePartitionGUID, sizeof (EFI_GUID));

    DEBUG ((EFI_D_INFO, " Index : %d\n", (UINT32) Index));
    DEBUG ((EFI_D_INFO, " Start LBA : %lx\n", (UINT64) HdDev.PartitionStart));
    DEBUG ((EFI_D_INFO, " End LBA : %lx\n", (UINT64) Entry->EndingLBA));
    DEBUG ((EFI_D_INFO, " Partition size: %lx\n", (UINT64) HdDev.PartitionSize));
    DEBUG ((EFI_D_INFO, " Start : %lx", MultU64x32 (Entry->StartingLBA, BlockSize)));
    DEBUG ((EFI_D_INFO, " End : %lx\n", MultU64x32 (Entry->EndingLBA, BlockSize)));

    Status = PartitionInstallChildHandle (
               This,
               Handle,
               DiskIo,
               BlockIo,
               BlockIo2,
               DevicePath,
               (EFI_DEVICE_PATH_PROTOCOL *) &HdDev,
               Entry->StartingLBA,
               Entry->EndingLBA,
               BlockSize,
               CompareGuid(&Entry->PartitionTypeGUID, &gEfiPartTypeSystemPartGuid)
               );
  }

  DEBUG ((EFI_D_INFO, "Prepare to Free Pool\n"));

Done:
  if (ProtectiveMbr != NULL) {
    FreePool (ProtectiveMbr);
  }
  if (PrimaryHeader != NULL) {
    FreePool (PrimaryHeader);
  }
  if (BackupHeader != NULL) {
    FreePool (BackupHeader);
  }
  if (PartEntry != NULL) {
    FreePool (PartEntry);
  }
  if (PEntryStatus != NULL) {
    FreePool (PEntryStatus);
  }

  return GptValidStatus;
}
/**
  Produces and returns an RNG value using either the default or specified RNG
  algorithm.

  @param[in]  This                    A pointer to the EFI_RNG_PROTOCOL
                                      instance.
  @param[in]  RNGAlgorithm            A pointer to the EFI_RNG_ALGORITHM that
                                      identifies the RNG algorithm to use. May
                                      be NULL in which case the function will
                                      use its default RNG algorithm.
  @param[in]  RNGValueLength          The length in bytes of the memory buffer
                                      pointed to by RNGValue. The driver shall
                                      return exactly this numbers of bytes.
  @param[out] RNGValue                A caller-allocated memory buffer filled
                                      by the driver with the resulting RNG
                                      value.

  @retval EFI_SUCCESS                 The RNG value was returned successfully.
  @retval EFI_UNSUPPORTED             The algorithm specified by RNGAlgorithm
                                      is not supported by this driver.
  @retval EFI_DEVICE_ERROR            An RNG value could not be retrieved due
                                      to a hardware or firmware error.
  @retval EFI_NOT_READY               There is not enough random data available
                                      to satisfy the length requested by
                                      RNGValueLength.
  @retval EFI_INVALID_PARAMETER       RNGValue is NULL or RNGValueLength is
                                      zero.

**/
STATIC
EFI_STATUS
EFIAPI
VirtioRngGetRNG (
  IN EFI_RNG_PROTOCOL            *This,
  IN EFI_RNG_ALGORITHM           *RNGAlgorithm, OPTIONAL
  IN UINTN                       RNGValueLength,
  OUT UINT8                      *RNGValue
  )
{
  VIRTIO_RNG_DEV            *Dev;
  DESC_INDICES              Indices;
  volatile UINT8            *Buffer;
  UINTN                     Index;
  UINT32                    Len;
  UINT32                    BufferSize;
  EFI_STATUS                Status;
  EFI_PHYSICAL_ADDRESS      DeviceAddress;
  VOID                      *Mapping;

  if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // We only support the raw algorithm, so reject requests for anything else
  //
  if (RNGAlgorithm != NULL &&
      !CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) {
    return EFI_UNSUPPORTED;
  }

  Buffer = (volatile UINT8 *)AllocatePool (RNGValueLength);
  if (Buffer == NULL) {
    return EFI_DEVICE_ERROR;
  }

  Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This);
  //
  // Map Buffer's system phyiscal address to device address
  //
  Status = VirtioMapAllBytesInSharedBuffer (
             Dev->VirtIo,
             VirtioOperationBusMasterWrite,
             (VOID *)Buffer,
             RNGValueLength,
             &DeviceAddress,
             &Mapping
             );
  if (EFI_ERROR (Status)) {
    Status = EFI_DEVICE_ERROR;
    goto FreeBuffer;
  }

  //
  // The Virtio RNG device may return less data than we asked it to, and can
  // only return MAX_UINT32 bytes per invocation. So loop as long as needed to
  // get all the entropy we were asked for.
  //
  for (Index = 0; Index < RNGValueLength; Index += Len) {
    BufferSize = (UINT32)MIN (RNGValueLength - Index, (UINTN)MAX_UINT32);

    VirtioPrepare (&Dev->Ring, &Indices);
    VirtioAppendDesc (&Dev->Ring,
      DeviceAddress + Index,
      BufferSize,
      VRING_DESC_F_WRITE,
      &Indices);

    if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) !=
        EFI_SUCCESS) {
      Status = EFI_DEVICE_ERROR;
      goto UnmapBuffer;
    }
    ASSERT (Len > 0);
    ASSERT (Len <= BufferSize);
  }

  //
  // Unmap the device buffer before accessing it.
  //
  Status = Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
  if (EFI_ERROR (Status)) {
    Status = EFI_DEVICE_ERROR;
    goto FreeBuffer;
  }

  for (Index = 0; Index < RNGValueLength; Index++) {
    RNGValue[Index] = Buffer[Index];
  }
  Status = EFI_SUCCESS;

UnmapBuffer:
  //
  // If we are reached here due to the error then unmap the buffer otherwise
  // the buffer is already unmapped after VirtioFlush().
  //
  if (EFI_ERROR (Status)) {
    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
  }

FreeBuffer:
  FreePool ((VOID *)Buffer);
  return Status;
}
Esempio n. 30
0
EFI_STATUS
EFIAPI
WinNtBusDriverBindingStart (
  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN  EFI_HANDLE                   ControllerHandle,
  IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
/*++

Routine Description:

Arguments:

Returns:

  None

--*/
// TODO:    This - add argument and description to function comment
// TODO:    ControllerHandle - add argument and description to function comment
// TODO:    RemainingDevicePath - add argument and description to function comment
// TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment
// TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment
// TODO:    EFI_SUCCESS - add return value to function comment
{
  EFI_STATUS                      Status;
  EFI_WIN_NT_THUNK_PROTOCOL       *WinNtThunk;
  EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;
  WIN_NT_BUS_DEVICE               *WinNtBusDevice;
  WIN_NT_IO_DEVICE                *WinNtDevice;
  UINTN                           Index;
  CHAR16                          *StartString;
  CHAR16                          *SubString;
  UINT16                          Count;
  UINTN                           StringSize;
  UINT16                          ComponentName[MAX_NT_ENVIRNMENT_VARIABLE_LENGTH];
  WIN_NT_VENDOR_DEVICE_PATH_NODE  *Node;
  BOOLEAN                         CreateDevice;
  CHAR16                          *TempStr;
  CHAR16                          *PcdTempStr;
  UINTN                           TempStrSize;

  Status = EFI_UNSUPPORTED;

  //
  // Grab the protocols we need
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &ParentDevicePath,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
    return Status;
  }

  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiWinNtThunkProtocolGuid,
                  (VOID **) &WinNtThunk,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
    return Status;
  }

  if (Status != EFI_ALREADY_STARTED) {
    WinNtBusDevice = AllocatePool (sizeof (WIN_NT_BUS_DEVICE));
    if (WinNtBusDevice == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }

    WinNtBusDevice->Signature           = WIN_NT_BUS_DEVICE_SIGNATURE;
    WinNtBusDevice->ControllerNameTable = NULL;

    AddUnicodeString2 (
      "eng",
      gWinNtBusDriverComponentName.SupportedLanguages,
      &WinNtBusDevice->ControllerNameTable,
      L"Windows Bus Controller",
      TRUE
      );
    AddUnicodeString2 (
      "en",
      gWinNtBusDriverComponentName2.SupportedLanguages,
      &WinNtBusDevice->ControllerNameTable,
      L"Windows Bus Controller",
      FALSE
      );


    Status = gBS->InstallMultipleProtocolInterfaces (
                    &ControllerHandle,
                    &gWinNtBusDriverGuid,
                    WinNtBusDevice,
                    NULL
                    );
    if (EFI_ERROR (Status)) {
      FreeUnicodeStringTable (WinNtBusDevice->ControllerNameTable);
      FreePool (WinNtBusDevice);
      return Status;
    }
  }

  //
  // Loop on the Variable list. Parse each variable to produce a set of handles that
  // represent virtual hardware devices.
  //
  for (Index = 0; Index < NT_PCD_ARRAY_SIZE; Index++) {
    PcdTempStr = (VOID *)LibPcdGetPtr (mPcdEnvironment[Index].Token);
    ASSERT (PcdTempStr != NULL);

    TempStrSize = StrLen (PcdTempStr);
    TempStr = AllocateMemory (((TempStrSize + 1) * sizeof (CHAR16)));
    StrCpy (TempStr, PcdTempStr);

    StartString = TempStr;

    //
    // Parse the envirnment variable into sub strings using '!' as a delimator.
    // Each substring needs it's own handle to be added to the system. This code
    // does not understand the sub string. Thats the device drivers job.
    //
    Count = 0;
    while (*StartString != '\0') {

      //
      // Find the end of the sub string
      //
      SubString = StartString;
      while (*SubString != '\0' && *SubString != '!') {
        SubString++;
      }

      if (*SubString == '!') {
        //
        // Replace token with '\0' to make sub strings. If this is the end
        //  of the string SubString will already point to NULL.
        //
        *SubString = '\0';
        SubString++;
      }

      CreateDevice = TRUE;
      if (RemainingDevicePath != NULL) {
        CreateDevice  = FALSE;
        //
        // Check if RemainingDevicePath is the End of Device Path Node, 
        // if yes, don't create any child device 
        //
        if (!IsDevicePathEnd (RemainingDevicePath)) {
          //
          // If RemainingDevicePath isn't the End of Device Path Node,
          // check its validation
          //
          Node          = (WIN_NT_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath;
          if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH &&
              Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP &&
              DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE)
              ) {
            if (CompareGuid (&Node->VendorDevicePath.Guid, mPcdEnvironment[Index].DevicePathGuid) &&
                Node->Instance == Count
                ) {
              CreateDevice = TRUE;
            }
          }
        }
      }

      if (CreateDevice) {

        //
        // Allocate instance structure, and fill in parent information.
        //
        WinNtDevice = AllocateMemory (sizeof (WIN_NT_IO_DEVICE));
        if (WinNtDevice == NULL) {
          return EFI_OUT_OF_RESOURCES;
        }

        WinNtDevice->Handle             = NULL;
        WinNtDevice->ControllerHandle   = ControllerHandle;
        WinNtDevice->ParentDevicePath   = ParentDevicePath;

        WinNtDevice->WinNtIo.WinNtThunk = WinNtThunk;

        //
        // Plus 2 to account for the NULL at the end of the Unicode string
        //
        StringSize = (UINTN) ((UINT8 *) SubString - (UINT8 *) StartString) + sizeof (CHAR16);
        WinNtDevice->WinNtIo.EnvString = AllocateMemory (StringSize);
        if (WinNtDevice->WinNtIo.EnvString != NULL) {
          CopyMem (WinNtDevice->WinNtIo.EnvString, StartString, StringSize);
        }

        WinNtDevice->ControllerNameTable = NULL;

        WinNtThunk->SPrintf (ComponentName, sizeof (ComponentName), L"%s", WinNtDevice->WinNtIo.EnvString);

        WinNtDevice->DevicePath = WinNtBusCreateDevicePath (
                                    ParentDevicePath,
                                    mPcdEnvironment[Index].DevicePathGuid,
                                    Count
                                    );
        if (WinNtDevice->DevicePath == NULL) {
          FreePool (WinNtDevice);
          return EFI_OUT_OF_RESOURCES;
        }

        AddUnicodeString2 (
          "eng",
          gWinNtBusDriverComponentName.SupportedLanguages,
          &WinNtDevice->ControllerNameTable,
          ComponentName,
          TRUE
          );
        AddUnicodeString2 (
          "en",
          gWinNtBusDriverComponentName2.SupportedLanguages,
          &WinNtDevice->ControllerNameTable,
          ComponentName,
          FALSE
          );


        WinNtDevice->WinNtIo.TypeGuid       = mPcdEnvironment[Index].DevicePathGuid;
        WinNtDevice->WinNtIo.InstanceNumber = Count;

        WinNtDevice->Signature              = WIN_NT_IO_DEVICE_SIGNATURE;

        Status = gBS->InstallMultipleProtocolInterfaces (
                        &WinNtDevice->Handle,
                        &gEfiDevicePathProtocolGuid,
                        WinNtDevice->DevicePath,
                        &gEfiWinNtIoProtocolGuid,
                        &WinNtDevice->WinNtIo,
                        NULL
                        );
        if (EFI_ERROR (Status)) {
          FreeUnicodeStringTable (WinNtDevice->ControllerNameTable);
          FreePool (WinNtDevice);
        } else {
          //
          // Open For Child Device
          //
          Status = gBS->OpenProtocol (
                          ControllerHandle,
                          &gEfiWinNtThunkProtocolGuid,
                          (VOID **) &WinNtThunk,
                          This->DriverBindingHandle,
                          WinNtDevice->Handle,
                          EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
                          );
        }
      }

      //
      // Parse Next sub string. This will point to '\0' if we are at the end.
      //
      Count++;
      StartString = SubString;
    }

    FreePool (TempStr);
  }

  return EFI_SUCCESS;
}