Beispiel #1
0
EFI_DEVICE_PATH *
AppendDevicePathNode (
    IN EFI_DEVICE_PATH  *Src1,
    IN EFI_DEVICE_PATH  *Src2
    )
// Src1 may have multiple "instances" and each instance is appended
// Src2 is a signal device path node (without a terminator) that is
// appended to each instance is Src1.
{
    EFI_DEVICE_PATH     *Temp, *Eop;
    UINTN               Length;

    //
    // Build a Src2 that has a terminator on it
    //

    Length = DevicePathNodeLength(Src2);
    Temp = AllocatePool (Length + sizeof(EFI_DEVICE_PATH));
    if (!Temp) {
        return NULL;
    }

    CopyMem (Temp, Src2, Length);
    Eop = NextDevicePathNode(Temp); 
    SetDevicePathEndNode(Eop);

    //
    // Append device paths
    //

    Src1 = AppendDevicePath (Src1, Temp);
    FreePool (Temp);
    return Src1;
}
Beispiel #2
0
EFI_DEVICE_PATH_PROTOCOL *
FileDevicePath (
  IN EFI_HANDLE       Device  OPTIONAL,
  IN CHAR16           *FileName
  )
/*++

Routine Description:
  Function allocates a device path for a file and appends it to an existing device path.

Arguments:
  Device         - A pointer to a device handle.

  FileName       - A pointer to a Null-terminated Unicode string.

Returns:

  If Device is not a valid device handle, then a device path for the file specified
  by FileName is allocated and returned.

  Results are allocated from pool.  The caller must FreePool the resulting device path
  structure

--*/
{
  UINTN                       Size;
  FILEPATH_DEVICE_PATH        *FilePath;
  EFI_DEVICE_PATH_PROTOCOL    *Eop, *DevicePath;

  Size = StrSize(FileName);
  FilePath = AllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof(EFI_DEVICE_PATH_PROTOCOL));
  DevicePath = NULL;

  if (FilePath) {

    //
    // Build a file path
    //
    FilePath->Header.Type = MEDIA_DEVICE_PATH;
    FilePath->Header.SubType = MEDIA_FILEPATH_DP;
    SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
    CopyMem (FilePath->PathName, FileName, Size);
    Eop = NextDevicePathNode(&FilePath->Header);
    SetDevicePathEndNode(Eop);

    //
    // Append file path to device's device path
    //
    DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) FilePath;
    if (Device) {
      DevicePath = AppendDevicePath (
                        DevicePathFromHandle(Device),
                        DevicePath
                        );
      FreePool(FilePath);
    }
  }

  return DevicePath;
}
Beispiel #3
0
/**
  Convert FvHandle and DriverName into an EFI device path

  @param  Fv                    Fv protocol, needed to read Depex info out of
                                FLASH.
  @param  FvHandle              Handle for Fv, needed in the
                                EFI_SMM_DRIVER_ENTRY so that the PE image can be
                                read out of the FV at a later time.
  @param  DriverName            Name of driver to add to mDiscoveredList.

  @return Pointer to device path constructed from FvHandle and DriverName

**/
EFI_DEVICE_PATH_PROTOCOL *
SmmFvToDevicePath (
  IN  EFI_FIRMWARE_VOLUME2_PROTOCOL   *Fv,
  IN  EFI_HANDLE                      FvHandle,
  IN  EFI_GUID                        *DriverName
  )
{
  EFI_STATUS                          Status;
  EFI_DEVICE_PATH_PROTOCOL            *FvDevicePath;
  EFI_DEVICE_PATH_PROTOCOL            *FileNameDevicePath;

  //
  // Remember the device path of the FV
  //
  Status = gBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
  if (EFI_ERROR (Status)) {
    FileNameDevicePath = NULL;
  } else {
    //
    // Build a device path to the file in the FV to pass into gBS->LoadImage
    //
    EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, DriverName);
    SetDevicePathEndNode (&mFvDevicePath.End);

    //
    // Note: FileNameDevicePath is in DXE memory
    //
    FileNameDevicePath = AppendDevicePath (
                            FvDevicePath,
                            (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath
                            );
  }
  return FileNameDevicePath;
}
Beispiel #4
0
EFIAPI
AppendDevicePathProtocolInterface (
  IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath,
  IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath
  )
{
  return AppendDevicePath (FirstDevicePath, SecondDevicePath);
}
Beispiel #5
0
EFIAPI
GetDevicePathTextForHandle(
  IN EFI_HANDLE TheHandle
  )
{
  EFI_STATUS                Status;
  EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
  EFI_DEVICE_PATH_PROTOCOL  *ImageDevicePath;
  EFI_DEVICE_PATH_PROTOCOL  *FinalPath;
  CHAR16                    *RetVal;

  FinalPath = NULL;

  Status = gBS->OpenProtocol (
                TheHandle,
                &gEfiLoadedImageProtocolGuid,
                (VOID**)&LoadedImage,
                gImageHandle,
                NULL,
                EFI_OPEN_PROTOCOL_GET_PROTOCOL
               );
  if (!EFI_ERROR (Status)) {
    Status = gBS->OpenProtocol (
                  LoadedImage->DeviceHandle,
                  &gEfiDevicePathProtocolGuid,
                  (VOID**)&ImageDevicePath,
                  gImageHandle,
                  NULL,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                 );
    if (!EFI_ERROR (Status)) {
      FinalPath = AppendDevicePath (ImageDevicePath, LoadedImage->FilePath);
      gBS->CloseProtocol(
        LoadedImage->DeviceHandle,
        &gEfiDevicePathProtocolGuid,
        gImageHandle,
        NULL);
    }
    gBS->CloseProtocol(
                TheHandle,
                &gEfiLoadedImageProtocolGuid,
                gImageHandle,
                NULL);
  }

  if (FinalPath == NULL) {
    return (NULL);
  }
  RetVal = gEfiShellProtocol->GetFilePathFromDevicePath(FinalPath);
  if (RetVal == NULL) {
    RetVal = gDevPathToText->ConvertDevicePathToText(FinalPath, TRUE, TRUE);
  }
  FreePool(FinalPath);
  return (RetVal);
}
Beispiel #6
0
EFI_STATUS
UpdateFdtPath (
  IN LIST_ENTRY *BootOptionsList
  )
{
  EFI_STATUS                Status;
  UINTN                     FdtDevicePathSize;
  BDS_SUPPORTED_DEVICE      *SupportedBootDevice;
  EFI_DEVICE_PATH_PROTOCOL  *FdtDevicePathNodes;
  EFI_DEVICE_PATH_PROTOCOL  *FdtDevicePath;

  Status = SelectBootDevice (&SupportedBootDevice);
  if (EFI_ERROR(Status)) {
    Status = EFI_ABORTED;
    goto EXIT;
  }

  // Create the specific device path node
  Status = SupportedBootDevice->Support->CreateDevicePathNode (L"FDT blob", &FdtDevicePathNodes);
  if (EFI_ERROR(Status)) {
    Status = EFI_ABORTED;
    goto EXIT;
  }

  if (FdtDevicePathNodes != NULL) {
    // Append the Device Path node to the select device path
    FdtDevicePath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, FdtDevicePathNodes);
    FdtDevicePathSize = GetDevicePathSize (FdtDevicePath);
    Status = gRT->SetVariable (
                    (CHAR16*)L"Fdt",
                    &gArmGlobalVariableGuid,
                    EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
                    FdtDevicePathSize,
                    FdtDevicePath
                    );
    ASSERT_EFI_ERROR(Status);
  } else {
    gRT->SetVariable (
           (CHAR16*)L"Fdt",
           &gArmGlobalVariableGuid,
           EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
           0,
           NULL
           );
    ASSERT_EFI_ERROR(Status);
  }

EXIT:
  if (Status == EFI_ABORTED) {
    Print(L"\n");
  }
  FreePool(SupportedBootDevice);
  return Status;
}
Beispiel #7
0
EFI_STATUS
BdsGetDeviceHd (
    IN  EFI_DEVICE_PATH*  RemovableDevicePath,
    OUT EFI_HANDLE*       DeviceHandle,
    OUT EFI_DEVICE_PATH** NewDevicePath
)
{
    EFI_STATUS                    Status;
    UINTN                         Index;
    UINTN                         PartitionHandleCount;
    EFI_HANDLE                    *PartitionBuffer;
    EFI_DEVICE_PATH*              PartitionDevicePath;
    EFI_DEVICE_PATH*              TmpDevicePath;
    HARDDRIVE_DEVICE_PATH*        HardDriveDevicePath1;
    HARDDRIVE_DEVICE_PATH*        HardDriveDevicePath2;

    // Get all the DiskIo handles
    PartitionHandleCount = 0;
    Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDiskIoProtocolGuid, NULL, &PartitionHandleCount, &PartitionBuffer);
    if (EFI_ERROR(Status) || (PartitionHandleCount == 0)) {
        return Status;
    }

    // Check if one of the handles matches the Hard Disk Description
    for (Index = 0; Index < PartitionHandleCount; Index++) {
        Status = gBS->HandleProtocol (PartitionBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **) &PartitionDevicePath);
        if (!EFI_ERROR(Status)) {
            TmpDevicePath = PartitionDevicePath;
            while (!IsDevicePathEnd (TmpDevicePath)) {
                // Check if the Device Path node is a HD Removable device Path node
                if (BdsIsRemovableHd (TmpDevicePath)) {
                    HardDriveDevicePath1 = (HARDDRIVE_DEVICE_PATH*)RemovableDevicePath;
                    HardDriveDevicePath2 = (HARDDRIVE_DEVICE_PATH*)TmpDevicePath;
                    if ((HardDriveDevicePath1->SignatureType == HardDriveDevicePath2->SignatureType) &&
                            (CompareGuid ((EFI_GUID *)HardDriveDevicePath1->Signature,(EFI_GUID *)HardDriveDevicePath2->Signature) == TRUE) &&
                            (HardDriveDevicePath1->PartitionNumber == HardDriveDevicePath2->PartitionNumber))
                    {
                        *DeviceHandle = PartitionBuffer[Index];
                        // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path
                        *NewDevicePath = AppendDevicePath (PartitionDevicePath, NextDevicePathNode(RemovableDevicePath));
                        return EFI_SUCCESS;
                    }
                }
                TmpDevicePath = NextDevicePathNode (TmpDevicePath);
            }

        }
    }

    return EFI_NOT_FOUND;
}
Beispiel #8
0
EFI_DEVICE_PATH_PROTOCOL *
AppendDevicePathNode (
  IN EFI_DEVICE_PATH_PROTOCOL  *Src1,
  IN EFI_DEVICE_PATH_PROTOCOL  *Src2
  )
/*++

Routine Description:
  Function is used to append a device path node to all the instances in another device path.

Arguments:
  Src1           - A pointer to a device path data structure.

  Src2           - A pointer to a device path data structure.

Returns:

  This function returns a pointer to the new device path.
  If there is not enough temporary pool memory available to complete this function,
  then NULL is returned.

  Src1 may have multiple "instances" and each instance is appended
  Src2 is a signal device path node (without a terminator) that is
  appended to each instance is Src1.

--*/
{
  EFI_DEVICE_PATH_PROTOCOL    *Temp, *Eop;
  UINTN                       Length;

  //
  // Build a Src2 that has a terminator on it
  //
  Length = DevicePathNodeLength(Src2);
  Temp = AllocatePool (Length + sizeof(EFI_DEVICE_PATH_PROTOCOL));
  if (!Temp) {
    return NULL;
  }

  CopyMem (Temp, Src2, Length);
  Eop = NextDevicePathNode(Temp);
  SetDevicePathEndNode(Eop);

  //
  // Append device paths
  //

  Src1 = AppendDevicePath (Src1, Temp);
  FreePool (Temp);
  return Src1;
}
Beispiel #9
0
EFI_DEVICE_PATH *
FileDevicePath (
    IN EFI_HANDLE       Device  OPTIONAL,
    IN CHAR16           *FileName
    )
/*++

    N.B. Results are allocated from pool.  The caller must FreePool
    the resulting device path structure

--*/
{
    UINTN                   Size;
    FILEPATH_DEVICE_PATH    *FilePath;
    EFI_DEVICE_PATH         *Eop, *DevicePath;    

    Size = StrSize(FileName);
    FilePath = (FILEPATH_DEVICE_PATH *) AllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof(EFI_DEVICE_PATH));
    DevicePath = (EFI_DEVICE_PATH *) NULL;

    if (FilePath) {

        //
        // Build a file path
        //

        FilePath->Header.Type = MEDIA_DEVICE_PATH;
        FilePath->Header.SubType = MEDIA_FILEPATH_DP;
        SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
        BS->CopyMem (FilePath->PathName, FileName, Size);
        Eop = NextDevicePathNode(&FilePath->Header);
        SetDevicePathEndNode(Eop);

        //
        // Append file path to device's device path
        //

        DevicePath = (EFI_DEVICE_PATH *) FilePath;
        if (Device) {
            DevicePath = AppendDevicePath (
                            DevicePathFromHandle(Device),
                            DevicePath
                            );

            BS->FreePool(FilePath);
        }
    }

    return DevicePath;
}
Beispiel #10
0
/*********************************************************************************
 * Name: FchD3ColdInit
 *
 * Description
 *   Entry point of the AMD FCH D3Cold support driver
 *
 * Input
 *   ImageHandle : EFI Image Handle for the DXE driver
 *   SystemTable : pointer to the EFI system table
 *
 * Output
 *   EFI_SUCCESS : Module initialized successfully
 *   EFI_ERROR   : Initialization failed (see error for more details)
 *
 *********************************************************************************/
EFI_STATUS
EFIAPI
FchD3ColdInit (
  IN    EFI_HANDLE                  ImageHandle,
  IN    EFI_SYSTEM_TABLE            *SystemTable
  )
{
  EFI_STATUS                        Status;
  BOOLEAN                           InSmm;
  EFI_SMM_BASE_PROTOCOL             *SmmBase;
  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
  EFI_DEVICE_PATH_PROTOCOL          *ImageDevicePath;
  EFI_DEVICE_PATH_PROTOCOL          *CompleteFilePath;
  FCH_INIT_PROTOCOL                 *pAmdFchInitProtocol;
  PSP_RESUME_SERVICE_PROTOCOL       *pAmdPspResumeServiceProtocol;
  EFI_HANDLE                        SmmImageHandle;
  EFI_HANDLE                        DispatchHandle;
  VOID                              *Registration;

  gST      = SystemTable;
  gBS      = SystemTable->BootServices;

  Status = gBS->LocateProtocol (
                  &gFchInitProtocolGuid,
                  NULL,
                  &pAmdFchInitProtocol
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  if (pAmdFchInitProtocol->FchPolicy.Misc.FchCsSupport.FchCsD3Cold == FALSE) {
    return EFI_UNSUPPORTED;
  }

  InSmm    = FALSE;
  Status = gBS->LocateProtocol (
                  &gEfiSmmBaseProtocolGuid,
                  NULL,
                  &SmmBase
                  );

  if (EFI_ERROR (Status)) {
    return Status;
  }
  SmmBase->GetSmstLocation (
             SmmBase,
             &mSmst
             );
  SmmBase->InSmm (
             SmmBase,
             &InSmm
             );


  if (!InSmm) {
    //
    // Register event
    //
    EfiLibCreateProtocolNotifyEvent (
      &gFchAcpiProtocolGuid,
      EFI_TPL_CALLBACK,
      FchD3ColdAcpiConfigureNotify,
      NULL,
      &Registration
      );

    EfiLibCreateProtocolNotifyEvent (
      &gFchAcpiTableInstallGuid,
      EFI_TPL_CALLBACK,
      FchD3ColdAcpiInstallNotify,
      NULL,
      &Registration
      );

    //
    // Not in SMM. Load this driver's image into SMRAM
    //
    if (ImageHandle != NULL) {
      Status = gBS->HandleProtocol (
                      ImageHandle,
                      &gEfiLoadedImageProtocolGuid,
                      &LoadedImage
                      );
      if (EFI_ERROR (Status)) {
        return Status;
      }

      Status = gBS->HandleProtocol (
                      LoadedImage->DeviceHandle,
                      &gEfiDevicePathProtocolGuid,
                      (VOID*) &ImageDevicePath
                      );

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

      CompleteFilePath = AppendDevicePath (
                           ImageDevicePath,
                           LoadedImage->FilePath
                           );

      // Load the image in memory to SMRAM, this automatically triggers SMI
      SmmBase->Register (
                 SmmBase,
                 CompleteFilePath,
                 NULL,
                 0,
                 &SmmImageHandle,
                 FALSE
                 );
    }
  } else {
    //
    // We're now in SMM!
    //
    Status = gBS->LocateProtocol (
                    &gFchInitProtocolGuid,
                    NULL,
                    &pAmdFchInitProtocol
                    );

    if (!EFI_ERROR (Status)) {
      EfiCopyMem (
        &gFchInitInSmm,
        pAmdFchInitProtocol,
        sizeof (FCH_INIT_PROTOCOL)
        );
    } else {
      return EFI_ABORTED;
    }

    Status = gBS->LocateProtocol (
                    &gPspResumeServiceProtocolGuid,
                    NULL,
                    &pAmdPspResumeServiceProtocol
                    );
    if (EFI_ERROR (Status)) {
      EfiLibCreateProtocolNotifyEvent (
        &gPspResumeServiceProtocolGuid,
        EFI_TPL_CALLBACK,
        FchCsResumeCallBackNotify,
        NULL,
        &Registration
        );
      return EFI_SUCCESS;
      //return Status;
    }
    Status = pAmdPspResumeServiceProtocol->Register (
                                             pAmdPspResumeServiceProtocol,
                                             &FchCsResumeCallBack,
                                             &gFchInitInSmm,
                                             0xFF,
                                             &DispatchHandle
                                             );
    return Status;
  }
  return EFI_SUCCESS;

}
Beispiel #11
0
EFI_STATUS
LinuxLoaderConfig (
  IN EFI_LOADED_IMAGE_PROTOCOL   *LoadedImage
  )
{
  EFI_STATUS                   Status;
  LINUX_LOADER_ACTION          Choice;
  UINTN                        BootOrderSize;
  UINT16*                      BootOrder;
  UINTN                        BootOrderCount;
  UINTN                        Index;
  CHAR16                       Description[MAX_ASCII_INPUT];
  CHAR8                        CmdLine[MAX_ASCII_INPUT];
  CHAR16                       Initrd[MAX_STR_INPUT];
  UINT16                       InitrdPathListLength;
  UINT16                       CmdLineLength;
  BDS_LOAD_OPTION*             BdsLoadOption;
  BDS_LOAD_OPTION**            SupportedBdsLoadOptions;
  UINTN                        SupportedBdsLoadOptionCount;
  LINUX_LOADER_OPTIONAL_DATA*  LinuxOptionalData;
  EFI_DEVICE_PATH*             DevicePathRoot;

  Choice = (LINUX_LOADER_ACTION)0;
  SupportedBdsLoadOptions = NULL;
  SupportedBdsLoadOptionCount = 0;

  do {
    Print (L"[%d] Create new Linux Boot Entry\n",LINUX_LOADER_NEW);
    Print (L"[%d] Update Linux Boot Entry\n",LINUX_LOADER_UPDATE);

    Print (L"Option: ");
    Status = GetHIInputInteger ((UINTN*)&Choice);
    if (Status == EFI_INVALID_PARAMETER) {
      Print (L"\n");
      return Status;
    } else if ((Choice != LINUX_LOADER_NEW) && (Choice != LINUX_LOADER_UPDATE)) {
      Print (L"Error: the option should be either '%d' or '%d'\n",LINUX_LOADER_NEW,LINUX_LOADER_UPDATE);
      Status = EFI_INVALID_PARAMETER;
    }
  } while (EFI_ERROR(Status));

  if (Choice == LINUX_LOADER_UPDATE) {
    // If no compatible entry then we just create a new entry
    Choice = LINUX_LOADER_NEW;

    // Scan the OptionalData of every entry for the correct signature
    Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);
    if (!EFI_ERROR(Status)) {
      BootOrderCount = BootOrderSize / sizeof(UINT16);

      // Allocate an array to handle maximum number of supported Boot Entry
      SupportedBdsLoadOptions = (BDS_LOAD_OPTION**)AllocatePool(sizeof(BDS_LOAD_OPTION*) * BootOrderCount);

      SupportedBdsLoadOptionCount = 0;

      // Check if the signature is present in the list of the current Boot entries
      for (Index = 0; Index < BootOrderCount; Index++) {
        Status = BootOptionFromLoadOptionIndex (BootOrder[Index], &BdsLoadOption);
        if (!EFI_ERROR(Status)) {
          if ((BdsLoadOption->OptionalDataSize >= sizeof(UINT32)) &&
              (*(UINT32*)BdsLoadOption->OptionalData == LINUX_LOADER_SIGNATURE)) {
            SupportedBdsLoadOptions[SupportedBdsLoadOptionCount++] = BdsLoadOption;
            Choice = LINUX_LOADER_UPDATE;
          }
        }
      }
    }
    FreePool (BootOrder);
  }

  if (Choice == LINUX_LOADER_NEW) {
    Description[0] = '\0';
    CmdLine[0]     = '\0';
    Initrd[0]      = '\0';

    BdsLoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION));

    DEBUG_CODE_BEGIN();
      CHAR16*                           DevicePathTxt;
      EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;

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

      Print(L"EFI OS Loader: %s\n",DevicePathTxt);

      FreePool(DevicePathTxt);
    DEBUG_CODE_END();

    //
    // Fill the known fields of BdsLoadOption
    //

    BdsLoadOption->Attributes = LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT;

    // Get the full Device Path for this file
    Status = gBS->HandleProtocol (LoadedImage->DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathRoot);
    ASSERT_EFI_ERROR(Status);

    BdsLoadOption->FilePathList = AppendDevicePath (DevicePathRoot, LoadedImage->FilePath);
    BdsLoadOption->FilePathListLength = GetDevicePathSize (BdsLoadOption->FilePathList);
  } else {
    if (SupportedBdsLoadOptionCount > 1) {
      for (Index = 0; Index < SupportedBdsLoadOptionCount; Index++) {
        Print (L"[%d] %s\n",Index + 1,SupportedBdsLoadOptions[Index]->Description);
      }

      do {
        Print (L"Update Boot Entry: ");
        Status = GetHIInputInteger ((UINTN*)&Choice);
        if (Status == EFI_INVALID_PARAMETER) {
          Print (L"\n");
          return Status;
        } else if ((Choice < 1) && (Choice > SupportedBdsLoadOptionCount)) {
          Print (L"Choose entry from 1 to %d\n",SupportedBdsLoadOptionCount);
          Status = EFI_INVALID_PARAMETER;
        }
      } while (EFI_ERROR(Status));
      BdsLoadOption = SupportedBdsLoadOptions[Choice-1];
    }
    StrnCpy (Description, BdsLoadOption->Description, MAX_STR_INPUT);

    LinuxOptionalData = (LINUX_LOADER_OPTIONAL_DATA*)BdsLoadOption->OptionalData;
    if (LinuxOptionalData->CmdLineLength > 0) {
      CopyMem (CmdLine, (CHAR8*)LinuxOptionalData + sizeof(LINUX_LOADER_OPTIONAL_DATA), LinuxOptionalData->CmdLineLength);
    } else {
      CmdLine[0] = '\0';
    }

    if (LinuxOptionalData->InitrdPathListLength > 0) {
      CopyMem (Initrd, (CHAR8*)LinuxOptionalData + sizeof(LINUX_LOADER_OPTIONAL_DATA) + LinuxOptionalData->CmdLineLength, LinuxOptionalData->InitrdPathListLength);
    } else {
      Initrd[0] = L'\0';
    }
    DEBUG((EFI_D_ERROR,"L\n"));
  }

  // Description
  Print (L"Description: ");
  Status = EditHIInputStr (Description, MAX_STR_INPUT);
  if (EFI_ERROR(Status)) {
    return Status;
  }
  if (StrLen (Description) == 0) {
    StrnCpy (Description, DEFAULT_BOOT_ENTRY_DESCRIPTION, MAX_STR_INPUT);
  }
  BdsLoadOption->Description = Description;

  // CmdLine
  Print (L"Command Line: ");
  Status = EditHIInputAscii (CmdLine, MAX_ASCII_INPUT);
  if (EFI_ERROR(Status)) {
    return Status;
  }

  // Initrd
  Print (L"Initrd name: ");
  Status = EditHIInputStr (Initrd, MAX_STR_INPUT);
  if (EFI_ERROR(Status)) {
    return Status;
  }

  CmdLineLength = AsciiStrLen (CmdLine);
  if (CmdLineLength > 0) {
    CmdLineLength += sizeof(CHAR8);
  }

  InitrdPathListLength = StrLen (Initrd) * sizeof(CHAR16);
  if (InitrdPathListLength > 0) {
    InitrdPathListLength += sizeof(CHAR16);
  }

  BdsLoadOption->OptionalDataSize = sizeof(LINUX_LOADER_OPTIONAL_DATA) + CmdLineLength + InitrdPathListLength;

  LinuxOptionalData = (LINUX_LOADER_OPTIONAL_DATA*)AllocatePool (BdsLoadOption->OptionalDataSize);
  BdsLoadOption->OptionalData = LinuxOptionalData;

  LinuxOptionalData->Signature = LINUX_LOADER_SIGNATURE;
  LinuxOptionalData->CmdLineLength = CmdLineLength;
  LinuxOptionalData->InitrdPathListLength = InitrdPathListLength;

  if (CmdLineLength > 0) {
    CopyMem (LinuxOptionalData + 1, CmdLine, CmdLineLength);
  }
  if (InitrdPathListLength > 0) {
    CopyMem ((UINT8*)(LinuxOptionalData + 1) + CmdLineLength, Initrd, InitrdPathListLength);
  }

  // Create or Update the boot entry
  Status = BootOptionToLoadOptionVariable (BdsLoadOption);

  return Status;
}
Beispiel #12
0
/**
  Execute registered handlers until one returns an error and that error is returned.
  If none of the handlers return an error, then EFI_SUCCESS is returned.

  Before exectue handler, get the image buffer by file device path if a handler 
  requires the image file. And return the image buffer to each handler when exectue handler.

  The handlers are executed in same order to their registered order.

  @param[in]  AuthenticationStatus 
                           This is the authentication type returned from the Section
                           Extraction protocol. See the Section Extraction Protocol
                           Specification for details on this type.
  @param[in]  FilePath     This is a pointer to the device path of the file that is
                           being dispatched. This will optionally be used for logging.

  @retval EFI_SUCCESS            The file specified by File did authenticate when more
                                 than one security handler services were registered, 
                                 or the file did not authenticate when no security 
                                 handler service was registered. And the platform policy 
                                 dictates that the DXE Core may use File.
  @retval EFI_INVALID_PARAMETER  File is NULL.
  @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and
                                 the platform policy dictates that File should be placed
                                 in the untrusted state. A file may be promoted from
                                 the untrusted to the trusted state at a future time
                                 with a call to the Trust() DXE Service.
  @retval EFI_ACCESS_DENIED      The file specified by File did not authenticate, and
                                 the platform policy dictates that File should not be
                                 used for any purpose.
**/
EFI_STATUS
EFIAPI
ExecuteSecurityHandlers (
  IN  UINT32                            AuthenticationStatus,
  IN  CONST EFI_DEVICE_PATH_PROTOCOL    *FilePath
  )
{
  UINT32        Index;
  EFI_STATUS    Status;
  UINT32        HandlerAuthenticationStatus;
  VOID          *FileBuffer;
  UINTN         FileSize;
  EFI_HANDLE    Handle;
  EFI_DEVICE_PATH_PROTOCOL        *Node;
  EFI_DEVICE_PATH_PROTOCOL        *FilePathToVerfiy;
  
  if (FilePath == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Directly return successfully when no handler is registered.
  //
  if (mNumberOfSecurityHandler == 0) {
    return EFI_SUCCESS;
  }
  
  Status                      = EFI_SUCCESS;
  FileBuffer                  = NULL;
  FileSize                    = 0;
  HandlerAuthenticationStatus = AuthenticationStatus;
  FilePathToVerfiy            = (EFI_DEVICE_PATH_PROTOCOL *) FilePath;
  //
  // Run security handler in same order to their registered list
  //
  for (Index = 0; Index < mNumberOfSecurityHandler; Index ++) {
    if ((mSecurityTable[Index].SecurityOperation & EFI_AUTH_OPERATION_IMAGE_REQUIRED) == EFI_AUTH_OPERATION_IMAGE_REQUIRED) {
      //
      // Try get file buffer when the handler requires image buffer.
      //
      if (FileBuffer == NULL) {
        Node   = FilePathToVerfiy;
        Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle);
        //
        // Try to get image by FALSE boot policy for the exact boot file path.
        //
        FileBuffer = GetFileBufferByFilePath (FALSE, FilePath, &FileSize, &AuthenticationStatus);
        if (FileBuffer == NULL) {
          //
          // Try to get image by TRUE boot policy for the inexact boot file path.
          //
          FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, &FileSize, &AuthenticationStatus);
        }
        if ((FileBuffer != NULL) && (!EFI_ERROR (Status))) {
          //
          // LoadFile () may cause the device path of the Handle be updated.
          //
          FilePathToVerfiy = AppendDevicePath (DevicePathFromHandle (Handle), Node);
        }
      }
    }
    Status = mSecurityTable[Index].SecurityHandler (
               HandlerAuthenticationStatus,
               FilePathToVerfiy,
               FileBuffer,
               FileSize
               );
    if (EFI_ERROR (Status)) {
      break;
    }
  }

  if (FileBuffer != NULL) {
    FreePool (FileBuffer);
  }
  if (FilePathToVerfiy != FilePath) {
    FreePool (FilePathToVerfiy);
  }

  return Status;
}
Beispiel #13
0
/**
  Searches all the available firmware volumes and returns the file device path of first matching
  FFS section.

  This function searches all the firmware volumes for FFS files with an FFS filename specified by NameGuid.
  The order that the firmware volumes is searched is not deterministic. For each FFS file found a search
  is made for FFS sections of type SectionType.

  If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,
  the search will be retried with a section type of EFI_SECTION_PE32.
  This function must be called with a TPL <= TPL_NOTIFY.

  If NameGuid is NULL, then ASSERT().

   @param  NameGuid             A pointer to to the FFS filename GUID to search for
                                within any of the firmware volumes in the platform.
   @param  SectionType          Indicates the FFS section type to search for within
                                the FFS file specified by NameGuid.
   @param  SectionInstance      Indicates which section instance within the FFS file
                                specified by NameGuid to retrieve.
   @param  FvFileDevicePath     Device path for the target FFS
                                file.

   @retval  EFI_SUCCESS           The specified file device path of FFS section was returned.
   @retval  EFI_NOT_FOUND         The specified file device path of FFS section could not be found.
   @retval  EFI_DEVICE_ERROR      The FFS section could not be retrieves due to a
                                  device error.
   @retval  EFI_ACCESS_DENIED     The FFS section could not be retrieves because the
                                  firmware volume that contains the matching FFS section does not
                                  allow reads.
   @retval  EFI_INVALID_PARAMETER FvFileDevicePath is NULL.

**/
EFI_STATUS
EFIAPI
GetFileDevicePathFromAnyFv (
  IN CONST  EFI_GUID                  *NameGuid,
  IN        EFI_SECTION_TYPE          SectionType,
  IN        UINTN                     SectionInstance,
  OUT       EFI_DEVICE_PATH_PROTOCOL  **FvFileDevicePath
  )
{
  EFI_STATUS                        Status;
  EFI_HANDLE                        *HandleBuffer;
  UINTN                             HandleCount;
  UINTN                             Index;
  EFI_HANDLE                        FvHandle;
  EFI_DEVICE_PATH_PROTOCOL          *FvDevicePath;
  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *TempFvFileDevicePath;
  VOID                              *Buffer;
  UINTN                             Size;

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

  HandleBuffer         = NULL;
  FvDevicePath         = NULL;
  TempFvFileDevicePath = NULL;
  Buffer               = NULL;
  Size                 = 0;

  //
  // Search the FV that contain the caller's FFS first.
  // FV builder can choose to build FFS into the this FV
  // so that this implementation of GetSectionFromAnyFv
  // will locate the FFS faster.
  //
  FvHandle = InternalImageHandleToFvHandle (gImageHandle);
  Status = InternalGetSectionFromFv (
             FvHandle,
             NameGuid,
             SectionType,
             SectionInstance,
             &Buffer,
             &Size
             );
  if (!EFI_ERROR (Status)) {
    goto Done;
  }

  Status = gBS->LocateHandleBuffer (
                  ByProtocol,
                  &gEfiFirmwareVolume2ProtocolGuid,
                  NULL,
                  &HandleCount,
                  &HandleBuffer
                  );
  if (EFI_ERROR (Status)) {
    goto Done;
  }

  for (Index = 0; Index < HandleCount; Index++) {
    //
    // Skip the FV that contain the caller's FFS
    //
    if (HandleBuffer[Index] != FvHandle) {
      Status = InternalGetSectionFromFv (
                 HandleBuffer[Index],
                 NameGuid,
                 SectionType,
                 SectionInstance,
                 &Buffer,
                 &Size
                 );

      if (!EFI_ERROR (Status)) {
        //
        // Update FvHandle to the current handle.
        //
        FvHandle = HandleBuffer[Index];
        goto Done;
      }
    }
  }

  if (Index == HandleCount) {
    Status = EFI_NOT_FOUND;
  }

Done:
  if (Status == EFI_SUCCESS) {
    //
    // Build a device path to the file in the FV to pass into gBS->LoadImage
    //
    Status = gBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
    if (EFI_ERROR (Status)) {
      *FvFileDevicePath = NULL;
    } else {
      TempFvFileDevicePath = AllocateZeroPool (sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + END_DEVICE_PATH_LENGTH);
      if (TempFvFileDevicePath == NULL) {
        *FvFileDevicePath = NULL;
        return EFI_OUT_OF_RESOURCES;
      }
      EfiInitializeFwVolDevicepathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)TempFvFileDevicePath, NameGuid);
      SetDevicePathEndNode (NextDevicePathNode (TempFvFileDevicePath));
      *FvFileDevicePath = AppendDevicePath (
                            FvDevicePath,
                            (EFI_DEVICE_PATH_PROTOCOL *)TempFvFileDevicePath
                            );
      FreePool (TempFvFileDevicePath);
    }
  }

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

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

  return Status;
}
Beispiel #14
0
EFI_STATUS
ExecElet (
  IN OUT EFI_NETWORK_TEST_FILE    *TestFile,
  IN CHAR16                       *TestNodeName
  )
/*++

Routine Description:

  Execute an application.

Arguments:

  TestFile      - Pointer to the EFI_EFI_NETWORK_TEST_FILE structure.
  TestNodeName  - Test node name string.

Returns:

  EFI_SUCCESS          - Operation succeeded.
  EFI_UNSUPPORTED      - Unsupported test file.
  EFI_OUT_OF_RESOURCES - Memory allocation failed.
  Others               - Some failure happened.
  
--*/
{
  EFI_STATUS                Status;
  UINTN                     ExitDataSize;
  CHAR16                    *ExitData;
  EFI_HANDLE                ImageHandle;
  EFI_DEVICE_PATH_PROTOCOL  *FileNode;
  EFI_DEVICE_PATH_PROTOCOL  *FilePath;
  EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
  UINT64                    StartTick;
  UINT64                    StopTick;

  if ((TestFile->Type == EFI_NETWORK_TEST_FILE_APPLICATION) && (TestNodeName == NULL)) {
    EFI_ENTS_DEBUG ((EFI_ENTS_D_TRACE, L"in ExecElet:begin exe (%s)", TestFile->FileName));

    //
    // Add the file path to the device path
    //
    FileNode = FileDevicePath (NULL, TestFile->FileName);
    if (FileNode == NULL) {
      EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"in ExecElet:Create file device path - %r", EFI_OUT_OF_RESOURCES));
      return EFI_OUT_OF_RESOURCES;
    }

    FilePath = AppendDevicePath (gEasFT->DevicePath, FileNode);
    if (FilePath == NULL) {
      EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"in ExecElet:Append file device path - %r", EFI_OUT_OF_RESOURCES));
      BS->FreePool (FileNode);
      return EFI_OUT_OF_RESOURCES;
    }

    BS->FreePool (FileNode);

    //
    // Load the test file
    //
    Status = BS->LoadImage (
                  FALSE,
                  gEasFT->ImageHandle,
                  FilePath,
                  NULL,
                  0,
                  &ImageHandle
                  );
    if (EFI_ERROR (Status)) {
      EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"in ExecElet:Load image - %r", Status));
      BS->FreePool (FilePath);
      return Status;
    }

    BS->FreePool (FilePath);
    EFI_ENTS_STATUS ((L"in ExecElet: Finish Loading image file <%s>", TestFile->FileName));

    //
    // Verify the image is an application or not
    //
    Status = BS->HandleProtocol (
                  ImageHandle,
                  &gEfiLoadedImageProtocolGuid,
                  (void **)&LoadedImage
                  );
    if (EFI_ERROR (Status)) {
      EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"in ExecElet: HandleProtocol - %r", Status));
	  BS->UnloadImage(ImageHandle);
      return Status;
    }

    if (LoadedImage->ImageCodeType == EfiLoaderCode) {
      //
      // It is an application
      //
#ifdef EFIARM
      StartTick = 0;
#else 
      StartTick = EfiReadTsc ();
#endif
      Status = BS->StartImage (
                    ImageHandle,
                    &ExitDataSize,
                    &ExitData
                    );
#ifdef EFIARM
      StopTick = 0;
#else 
      StopTick = EfiReadTsc ();
#endif
      RecordExecTime (StartTick, StopTick);
      if (EFI_ERROR (Status)) {
        EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"Error in ExecElet: Start image - %r\n", Status));
      }
    } else {
      EFI_ENTS_DEBUG ((EFI_ENTS_D_WARNING, L"Unsupported test file"));
      Status = EFI_UNSUPPORTED;
    }
	BS->UnloadImage(ImageHandle);
	return Status;
  } else if ((TestFile->Type == EFI_NETWORK_TEST_FILE_DRIVER) && (TestNodeName != NULL)) {
    EFI_ENTS_DEBUG ((EFI_ENTS_D_TRACE, L"in ExecElet:begin exe (%s->%s)", TestFile->CmdName, TestNodeName));

    Status = ExecDriver (TestFile, TestNodeName);
    if (EFI_ERROR (Status)) {
      EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"Error in ExecDriver: Status - %r\n", Status));
      return Status;
    }
  }

  return EFI_SUCCESS;
}
Beispiel #15
0
/**
Internal work function to fill in EFI_OPEN_FILE information for the Fs and BlkIo

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


**/
EFI_STATUS
EblFileDevicePath (
  IN OUT EFI_OPEN_FILE  *File,
  IN  CHAR8             *FileName,
  IN  CONST UINT64      OpenMode
  )
{
  EFI_STATUS                        Status;
  UINTN                             Size;
  FILEPATH_DEVICE_PATH              *FilePath;
  EFI_DEVICE_PATH_PROTOCOL          *FileDevicePath;
  CHAR16                            UnicodeFileName[MAX_PATHNAME];
  EFI_BLOCK_IO_PROTOCOL             *BlkIo;
  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Fs;
  EFI_FILE_HANDLE                   Root;


  if ( *FileName != 0 ) {
    AsciiStrToUnicodeStr (FileName, UnicodeFileName);
  } else {
    AsciiStrToUnicodeStr ("\\", UnicodeFileName);
  }

  Size = StrSize (UnicodeFileName);
  FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof (EFI_DEVICE_PATH_PROTOCOL));
  if (FileDevicePath != NULL) {
    FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath;
    FilePath->Header.Type    = MEDIA_DEVICE_PATH;
    FilePath->Header.SubType = MEDIA_FILEPATH_DP;
    CopyMem (&FilePath->PathName, UnicodeFileName, Size);
    SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
    SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header));

    if (File->EfiHandle != NULL) {
      File->DevicePath = DevicePathFromHandle (File->EfiHandle);
    }

    File->DevicePath = AppendDevicePath (File->DevicePath, FileDevicePath);
    FreePool (FileDevicePath);
  }

  Status = gBS->HandleProtocol (File->EfiHandle, &gEfiBlockIoProtocolGuid, (VOID **)&BlkIo);
  if (!EFI_ERROR (Status)) {
    File->FsBlockIoMedia = BlkIo->Media;
    File->FsBlockIo = BlkIo;

    // If we are not opening the device this will get over written with file info
    File->MaxPosition = MultU64x32 (BlkIo->Media->LastBlock + 1, BlkIo->Media->BlockSize);
  }

  if (File->Type == EfiOpenFileSystem) {
    Status = gBS->HandleProtocol (File->EfiHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
    if (!EFI_ERROR (Status)) {
      Status = Fs->OpenVolume (Fs, &Root);
      if (!EFI_ERROR (Status)) {
        // Get information about the volume
        Size = 0;
        Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, File->FsInfo);
        if (Status == EFI_BUFFER_TOO_SMALL) {
          File->FsInfo = AllocatePool (Size);
          Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, File->FsInfo);
        }

        // Get information about the file
        Status = Root->Open (Root, &File->FsFileHandle, UnicodeFileName, OpenMode, 0);
        if (!EFI_ERROR (Status)) {
          Size = 0;
          Status = File->FsFileHandle->GetInfo (File->FsFileHandle, &gEfiFileInfoGuid, &Size, NULL);
          if (Status == EFI_BUFFER_TOO_SMALL) {
            File->FsFileInfo = AllocatePool (Size);
            Status = File->FsFileHandle->GetInfo (File->FsFileHandle, &gEfiFileInfoGuid, &Size, File->FsFileInfo);
            if (!EFI_ERROR (Status)) {
              File->Size = (UINTN)File->FsFileInfo->FileSize;
              File->MaxPosition = (UINT64)File->Size;
            }
          }
        }

        Root->Close (Root);
      }
    }
  } else if (File->Type == EfiOpenBlockIo) {
    File->Size = (UINTN)File->MaxPosition;
  }

  return Status;
}
Beispiel #16
0
/********************************************************************************
 * Name: AmdFchWheaInitEntry
 *
 * Description
 *   AmdFchWheaInit Entrypoint
 *
 * Input
 *
 * Output
 *   EFI_UNSUPPORTED : unsupported function
 *
 *********************************************************************************/
EFI_STATUS
AmdFchWheaInitEntry (
  IN EFI_HANDLE                             ImageHandle,
  IN EFI_SYSTEM_TABLE                       *SystemTable
  )
{
  EFI_STATUS                                Status;
  BOOLEAN                                   InSmm;
  FCH_INIT_PROTOCOL                         *AmdFchInit;
  EFI_SMM_BASE_PROTOCOL                     *SmmBase;
  FCH_SMM_SW_DISPATCH_PROTOCOL              *AmdSwDispatch;
  FCH_SMM_SW_REGISTER_CONTEXT               SwRegisterContext;
  EFI_HANDLE                                SwHandle;
  FCH_SMM_MISC_DISPATCH_PROTOCOL            *AmdFchSmmMiscDispatch;
  FCH_SMM_MISC_REGISTER_CONTEXT             MiscRegisterContext;
  EFI_HANDLE                                MiscHandle;
  EFI_SMM_SYSTEM_TABLE                      *mSmst;
  EFI_LOADED_IMAGE_PROTOCOL                 *LoadedImage;
  EFI_DEVICE_PATH_PROTOCOL                  *ImageDevicePath;
  EFI_DEVICE_PATH_PROTOCOL                  *CompleteFilePath;
  EFI_HANDLE                                SmmImageHandle;
  EFI_EVENT                                 InstallAmdTableEvent;
  EFI_HANDLE                                Handle;
  UINT8                                     *buffer;

  InSmm    = FALSE;
  DxeInitializeDriverLib (ImageHandle, SystemTable);

  Status = gBS->LocateProtocol (
                  &gFchInitProtocolGuid,
                  NULL,
                  &AmdFchInit
                  );
  ASSERT_EFI_ERROR (Status);

  if (AmdFchInit->FchPolicy.Gpp.PcieAer == 0) {
    return Status;
  }

  Status = gBS->LocateProtocol (
                  &gEfiSmmBaseProtocolGuid,
                  NULL,
                  &SmmBase
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  SmmBase->GetSmstLocation (
             SmmBase,
             &mSmst
             );
  SmmBase->InSmm (
             SmmBase,
             &InSmm
             );

  if (!InSmm) {
    Status = EfiCreateEventReadyToBoot (
               EFI_TPL_CALLBACK,
               AmdWheaCheckInstallTables,
               NULL,
               &InstallAmdTableEvent
               );

    //
    //  Allocate memory and Initialize for Data block
    //
    Status = gBS->AllocatePool (
                    EfiReservedMemoryType,
                    sizeof (AMD_FCH_WHEA_EINJ_BUFFER),
                    (VOID **)&buffer
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    EfiZeroMem (buffer, sizeof (AMD_FCH_WHEA_EINJ_BUFFER));

    mEinjData = (AMD_FCH_WHEA_EINJ_BUFFER *)buffer;
    mEinjData->Valid             = FALSE;
    mEinjData->PlatformEinjValid = FALSE;

    //
    //  Allocate memory and Initialize for Error Data block
    //
    Status = gBS->AllocatePool (
                    EfiReservedMemoryType,
                    MAX_ERROR_BLOCK_SIZE,
                    (VOID **)&buffer
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    EfiZeroMem (buffer, MAX_ERROR_BLOCK_SIZE);

    mEinjData->AmdHwErrBlk = (GENERIC_ERROR_STATUS_BLOCK *)buffer;

    AmdErrBlkAddressUpdate ();

    Handle = ImageHandle;
    Status = gBS->InstallProtocolInterface (
                    &Handle,
                    &mEfiAmdFchWheaDataGuid,
                    EFI_NATIVE_INTERFACE,
                    mEinjData
                    );
    if (EFI_ERROR (Status)) {
      return (Status);
    }

    if (ImageHandle != NULL) {
      Status = gBS->HandleProtocol (
                      ImageHandle,
                      &gEfiLoadedImageProtocolGuid,
                      &LoadedImage
                      );
      if (EFI_ERROR (Status)) {
        return Status;
      }

      Status = gBS->HandleProtocol (
                      LoadedImage->DeviceHandle,
                      &gEfiDevicePathProtocolGuid,
                      (VOID*) &ImageDevicePath
                      );
      if (EFI_ERROR (Status)) {
        return Status;
      }

      CompleteFilePath = AppendDevicePath (
                           ImageDevicePath,
                           LoadedImage->FilePath
                           );

      // Load the image in memory to SMRAM, this automatically triggers SMI
      SmmBase->Register (
                 SmmBase,
                 CompleteFilePath,
                 NULL,
                 0,
                 &SmmImageHandle,
                 FALSE
                 );
    }
  } else {
    Status = gBS->LocateProtocol (
                    &mEfiAmdFchWheaDataGuid,
                    NULL,
                    &mEinjData
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    Status = gBS->LocateProtocol (
                    &gFchSmmSwDispatchProtocolGuid,
                    NULL,
                    &AmdSwDispatch
                    );
    ASSERT_EFI_ERROR (Status);

    SwRegisterContext.AmdSwValue  = EINJ_TRIGGER_ACTION_SWSMI;
    Status = AmdSwDispatch->Register (
                              AmdSwDispatch,
                              AmdSmiEinjTriggerActionCallBack,
                              &SwRegisterContext,
                              &SwHandle
                              );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    Status = gBS->LocateProtocol (
                    &gFchSmmMiscDispatchProtocolGuid,
                    NULL,
                    &AmdFchSmmMiscDispatch
                    );
    ASSERT_EFI_ERROR (Status);

    MiscRegisterContext.SmiStatusReg = FCH_SMI_REG88;
    MiscRegisterContext.SmiStatusBit = BIT21;
    MiscRegisterContext.Order        = 0x80;
    Status = AmdFchSmmMiscDispatch->Register (
                                      AmdFchSmmMiscDispatch,
                                      AmdMiscFchWheaHwSmiCallback,
                                      &MiscRegisterContext,
                                      &MiscHandle
                                      );

    MiscRegisterContext.SmiStatusReg = FCH_SMI_REG88;
    MiscRegisterContext.SmiStatusBit = BIT22;
    MiscRegisterContext.Order        = 0x80;
    Status = AmdFchSmmMiscDispatch->Register (
                                      AmdFchSmmMiscDispatch,
                                      AmdMiscFchWheaHwSmiCallback,
                                      &MiscRegisterContext,
                                      &MiscHandle
                                      );

    MiscRegisterContext.SmiStatusReg = FCH_SMI_REG88;
    MiscRegisterContext.SmiStatusBit = BIT23;
    MiscRegisterContext.Order        = 0x80;
    Status = AmdFchSmmMiscDispatch->Register (
                                      AmdFchSmmMiscDispatch,
                                      AmdMiscFchWheaHwSmiCallback,
                                      &MiscRegisterContext,
                                      &MiscHandle
                                      );

    MiscRegisterContext.SmiStatusReg = FCH_SMI_REG88;
    MiscRegisterContext.SmiStatusBit = BIT24;
    MiscRegisterContext.Order        = 0x80;
    Status = AmdFchSmmMiscDispatch->Register (
                                      AmdFchSmmMiscDispatch,
                                      AmdMiscFchWheaHwSmiCallback,
                                      &MiscRegisterContext,
                                      &MiscHandle
                                      );

    ACPIMMIO32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REGB4) &= ~(BIT11 + BIT13 + BIT15 + BIT17);
    ACPIMMIO32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REGB4) |= (BIT10 + BIT12 + BIT14 + BIT16);
  }
  return Status;
}
Beispiel #17
0
EFI_STATUS
add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments)
{
	CHAR16 *fullpath = NULL;
	UINT64 pathlen = 0;
	EFI_STATUS rc = EFI_SUCCESS;

	rc = make_full_path(dirname, filename, &fullpath, &pathlen);
	if (EFI_ERROR(rc))
		return rc;
	
	EFI_DEVICE_PATH *dph = NULL, *dpf = NULL, *dp = NULL;
	
	dph = DevicePathFromHandle(this_image->DeviceHandle);
	if (!dph) {
		rc = EFI_OUT_OF_RESOURCES;
		goto err;
	}

	dpf = FileDevicePath(fh, fullpath);
	if (!dpf) {
		rc = EFI_OUT_OF_RESOURCES;
		goto err;
	}

	dp = AppendDevicePath(dph, dpf);
	if (!dp) {
		rc = EFI_OUT_OF_RESOURCES;
		goto err;
	}

#ifdef DEBUG_FALLBACK
	UINTN s = DevicePathSize(dp);
	int i;
	UINT8 *dpv = (void *)dp;
	for (i = 0; i < s; i++) {
		if (i > 0 && i % 16 == 0)
			Print(L"\n");
		Print(L"%02x ", dpv[i]);
	}
	Print(L"\n");

	CHAR16 *dps = DevicePathToStr(dp);
	Print(L"device path: \"%s\"\n", dps);
#endif
	if (!first_new_option) {
		CHAR16 *dps = DevicePathToStr(dp);
		Print(L"device path: \"%s\"\n", dps);
		first_new_option = DuplicateDevicePath(dp);
		first_new_option_args = arguments;
		first_new_option_size = StrLen(arguments) * sizeof (CHAR16);
	}

	add_boot_option(dp, fullpath, label, arguments);

err:
	if (dpf)
		FreePool(dpf);
	if (dp)
		FreePool(dp);
	if (fullpath)
		FreePool(fullpath);
	return rc;
}
Beispiel #18
0
EFI_STATUS
FchSmmEntryPoint (
  IN       EFI_HANDLE         ImageHandle,
  IN       EFI_SYSTEM_TABLE   *SystemTable
  )

{
  FCH_INIT_PROTOCOL            *pFchCimxInitProtocol;
  EFI_STATUS                      Status;
  BOOLEAN                         InSmm;
  EFI_SMM_BASE_PROTOCOL           *SmmBase;
  EFI_LOADED_IMAGE_PROTOCOL       *LoadedImage;
  EFI_DEVICE_PATH_PROTOCOL        *ImageDevicePath;
  EFI_DEVICE_PATH_PROTOCOL        *CompleteFilePath;
  EFI_HANDLE                      SmmImageHandle;

  //
  // Initialize EFI library
  //
  InSmm    = FALSE;
  gST      = SystemTable;
  gBS      = SystemTable->BootServices;

  Status = gBS->LocateProtocol (
                  &gEfiSmmBaseProtocolGuid,
                  NULL,
                  &SmmBase
                  );

  if (EFI_ERROR (Status)) {
    return Status;
  }
  SmmBase->GetSmstLocation (
             SmmBase,
             &mSmst
             );
  SmmBase->InSmm (
             SmmBase,
             &InSmm
             );


  if (!InSmm) {
    //
    // Not in SMM. Load this driver's image into SMRAM
    //
    if (ImageHandle != NULL) {
      Status = gBS->HandleProtocol (
                      ImageHandle,
                      &gEfiLoadedImageProtocolGuid,
                      &LoadedImage
                      );
      if (EFI_ERROR (Status)) {
        return Status;
      }

      Status = gBS->HandleProtocol (
                      LoadedImage->DeviceHandle,
                      &gEfiDevicePathProtocolGuid,
                      (VOID*) &ImageDevicePath
                      );

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

      CompleteFilePath = AppendDevicePath (
                           ImageDevicePath,
                           LoadedImage->FilePath
                           );

      // Load the image in memory to SMRAM, this automatically triggers SMI
      SmmBase->Register (
                 SmmBase,
                 CompleteFilePath,
                 NULL,
                 0,
                 &SmmImageHandle,
                 FALSE
                 );
    }
  } else {
    //
    // We're now in SMM!
    //

    //
    // Initialize global variables
    //
    Status = mSmst->SmmAllocatePool (
                      EfiRuntimeServicesData,
                      0x100,
                      &mFchPciIrqRoutingTable
                      );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    Status = gBS->LocateProtocol (
                    &gFchInitProtocolGuid,
                    NULL,
                    &pFchCimxInitProtocol
                    );
    if (!EFI_ERROR (Status)) {
      EfiCopyMem (
        &gFchInitInSmm,
        pFchCimxInitProtocol,
        sizeof (FCH_INIT_PROTOCOL)
        );
    } else {
      return EFI_ABORTED;
    }

    Status = FchSmmRegistrationCenter ();
    return Status;
  }
  return Status;
}
Beispiel #19
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;
}
Beispiel #20
0
EFI_STATUS
LoadSingleSupportFile (
  IN EFI_DEVICE_PATH_PROTOCOL     *DevicePath,
  IN CHAR16                       *FileName,
  OUT EFI_SCT_TEST_FILE           **SupportFile
  )
/*++

Routine Description:

  Load a test support file.

--*/
{
  EFI_STATUS                  Status;
  EFI_HANDLE                  ImageHandle;
  EFI_DEVICE_PATH_PROTOCOL    *FileNode;
  EFI_DEVICE_PATH_PROTOCOL    *FilePath;
  EFI_LOADED_IMAGE_PROTOCOL   *LoadedImage;
  UINTN                       ExitDataSize;
  CHAR16                      *ExitData;
  EFI_TSL_INIT_INTERFACE      *TslInit;

  //
  // Check parameters
  //
  if ((DevicePath == NULL) || (FileName == NULL) || (SupportFile == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Debug information
  //
  EFI_SCT_DEBUG ((EFI_SCT_D_TRACE, L"Load support file <%s>", FileName));

  //
  // Add the file path to the device path
  //
  FileNode = FileDevicePath (NULL, FileName);
  if (FileNode == NULL) {
    EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"FileDevicePath: Out of resources"));
    return EFI_OUT_OF_RESOURCES;
  }

  FilePath = AppendDevicePath (DevicePath, FileNode);
  if (FilePath == NULL) {
    EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"AppendDevicePath: Out of resources"));
    BS->FreePool (FileNode);
    return EFI_OUT_OF_RESOURCES;
  }

  BS->FreePool (FileNode);

  //
  // Load the support file
  //
  Status = BS->LoadImage (
                 FALSE,
                 gFT->ImageHandle,
                 FilePath,
                 NULL,
                 0,
                 &ImageHandle
                 );
  if (EFI_ERROR (Status)) {
    EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Load image - %r", Status));
    BS->FreePool (FilePath);
    return Status;
  }

  BS->FreePool (FilePath);

  //
  // Verify the image is a driver or not
  //
  Status = BS->HandleProtocol (
                 ImageHandle,
                 &gEfiLoadedImageProtocolGuid,
                 &LoadedImage
                 );
  if (EFI_ERROR (Status)) {
    EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Locate loaded image - %r", Status));
    return Status;
  }

  if ((LoadedImage->ImageCodeType == EfiBootServicesCode   ) ||
      (LoadedImage->ImageCodeType == EfiRuntimeServicesCode)) {
    //
    // It is a driver, and then verify it is a TSL (test support library)
    //
    Status = BS->StartImage (
                   ImageHandle,
                   &ExitDataSize,
                   &ExitData
                   );
    if (EFI_ERROR (Status)) {
      EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Start image - %r", Status));
      return Status;
    }

    //
    // Is it a test support library?
    //
    Status = BS->HandleProtocol (
                   ImageHandle,
                   &gEfiTslInitInterfaceGuid,
                   &TslInit
                   );
    if (!EFI_ERROR (Status)) {
      Status = CreateSingleSupportFile (
                 DevicePath,
                 FileName,
                 ImageHandle,
                 TslInit,
                 SupportFile
                 );
      if (EFI_ERROR (Status)) {
        EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Create a support file - %r", Status));
        BS->UnloadImage (ImageHandle);
        return Status;
      }

      return EFI_SUCCESS;
    }

    BS->UnloadImage (ImageHandle);
  }

  //
  // Unsupported file
  //
  EFI_SCT_DEBUG ((EFI_SCT_D_DEBUG, L"Unsupported file"));
  return EFI_UNSUPPORTED;
}
Beispiel #21
0
EFI_STATUS
add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments)
{
	CHAR16 *fullpath = NULL;
	UINT64 pathlen = 0;
	EFI_STATUS rc = EFI_SUCCESS;

	rc = make_full_path(dirname, filename, &fullpath, &pathlen);
	if (EFI_ERROR(rc))
		return rc;
	
	EFI_DEVICE_PATH *dph = NULL;
	EFI_DEVICE_PATH *file = NULL;
	EFI_DEVICE_PATH *full_device_path = NULL;
	EFI_DEVICE_PATH *dp = NULL;
	
	dph = DevicePathFromHandle(this_image->DeviceHandle);
	if (!dph) {
		rc = EFI_OUT_OF_RESOURCES;
		goto err;
	}

	file = FileDevicePath(fh, fullpath);
	if (!file) {
		rc = EFI_OUT_OF_RESOURCES;
		goto err;
	}

	full_device_path = AppendDevicePath(dph, file);
	if (!full_device_path) {
		rc = EFI_OUT_OF_RESOURCES;
		goto err;
	}

	rc = FindSubDevicePath(full_device_path,
				MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, &dp);
	if (EFI_ERROR(rc)) {
		if (rc == EFI_NOT_FOUND) {
			dp = full_device_path;
		} else {
			rc = EFI_OUT_OF_RESOURCES;
			goto err;
		}
	}

#ifdef DEBUG_FALLBACK
	{
	UINTN s = DevicePathSize(dp);
	UINTN i;
	UINT8 *dpv = (void *)dp;
	for (i = 0; i < s; i++) {
		if (i > 0 && i % 16 == 0)
			Print(L"\n");
		Print(L"%02x ", dpv[i]);
	}
	Print(L"\n");

	CHAR16 *dps = DevicePathToStr(dp);
	Print(L"device path: \"%s\"\n", dps);
	}
#endif

	UINT16 option;
	rc = find_boot_option(dp, full_device_path, fullpath, label, arguments, &option);
	if (EFI_ERROR(rc)) {
		add_boot_option(dp, full_device_path, fullpath, label, arguments);
	} else if (option != 0) {
		CHAR16 *newbootorder;
		newbootorder = AllocateZeroPool(sizeof (CHAR16) * nbootorder);
		if (!newbootorder)
			return EFI_OUT_OF_RESOURCES;

		newbootorder[0] = bootorder[option];
		CopyMem(newbootorder + 1, bootorder, sizeof (CHAR16) * option);
		CopyMem(newbootorder + option + 1, bootorder + option + 1,
			sizeof (CHAR16) * (nbootorder - option - 1));
		FreePool(bootorder);
		bootorder = newbootorder;
	}

err:
	if (file)
		FreePool(file);
	if (full_device_path)
		FreePool(full_device_path);
	if (dp)
		FreePool(dp);
	if (fullpath)
		FreePool(fullpath);
	return rc;
}
Beispiel #22
0
EFI_STATUS
BdsGetDeviceUsb (
    IN  EFI_DEVICE_PATH*  RemovableDevicePath,
    OUT EFI_HANDLE*       DeviceHandle,
    OUT EFI_DEVICE_PATH** NewDevicePath
)
{
    EFI_STATUS                    Status;
    UINTN                         Index;
    UINTN                         UsbIoHandleCount;
    EFI_HANDLE                    *UsbIoBuffer;
    EFI_DEVICE_PATH*              UsbIoDevicePath;
    EFI_DEVICE_PATH*              TmpDevicePath;
    USB_WWID_DEVICE_PATH*         WwidDevicePath1;
    USB_WWID_DEVICE_PATH*         WwidDevicePath2;
    USB_CLASS_DEVICE_PATH*        UsbClassDevicePath1;
    USB_CLASS_DEVICE_PATH*        UsbClassDevicePath2;

    // Get all the UsbIo handles
    UsbIoHandleCount = 0;
    Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiUsbIoProtocolGuid, NULL, &UsbIoHandleCount, &UsbIoBuffer);
    if (EFI_ERROR(Status) || (UsbIoHandleCount == 0)) {
        return Status;
    }

    // Check if one of the handles matches the USB description
    for (Index = 0; Index < UsbIoHandleCount; Index++) {
        Status = gBS->HandleProtocol (UsbIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **) &UsbIoDevicePath);
        if (!EFI_ERROR(Status)) {
            TmpDevicePath = UsbIoDevicePath;
            while (!IsDevicePathEnd (TmpDevicePath)) {
                // Check if the Device Path node is a USB Removable device Path node
                if (BdsIsRemovableUsb (TmpDevicePath)) {
                    if (TmpDevicePath->SubType == MSG_USB_WWID_DP) {
                        WwidDevicePath1 = (USB_WWID_DEVICE_PATH*)RemovableDevicePath;
                        WwidDevicePath2 = (USB_WWID_DEVICE_PATH*)TmpDevicePath;
                        if ((WwidDevicePath1->VendorId == WwidDevicePath2->VendorId) &&
                                (WwidDevicePath1->ProductId == WwidDevicePath2->ProductId) &&
                                (CompareMem (WwidDevicePath1+1, WwidDevicePath2+1, DevicePathNodeLength(WwidDevicePath1)-sizeof(USB_WWID_DEVICE_PATH)) == 0))
                        {
                            *DeviceHandle = UsbIoBuffer[Index];
                            // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path
                            *NewDevicePath = AppendDevicePath (UsbIoDevicePath, NextDevicePathNode(RemovableDevicePath));
                            return EFI_SUCCESS;
                        }
                    } else {
                        UsbClassDevicePath1 = (USB_CLASS_DEVICE_PATH*)RemovableDevicePath;
                        UsbClassDevicePath2 = (USB_CLASS_DEVICE_PATH*)TmpDevicePath;
                        if ((UsbClassDevicePath1->VendorId != 0xFFFF) && (UsbClassDevicePath1->VendorId == UsbClassDevicePath2->VendorId) &&
                                (UsbClassDevicePath1->ProductId != 0xFFFF) && (UsbClassDevicePath1->ProductId == UsbClassDevicePath2->ProductId) &&
                                (UsbClassDevicePath1->DeviceClass != 0xFF) && (UsbClassDevicePath1->DeviceClass == UsbClassDevicePath2->DeviceClass) &&
                                (UsbClassDevicePath1->DeviceSubClass != 0xFF) && (UsbClassDevicePath1->DeviceSubClass == UsbClassDevicePath2->DeviceSubClass) &&
                                (UsbClassDevicePath1->DeviceProtocol != 0xFF) && (UsbClassDevicePath1->DeviceProtocol == UsbClassDevicePath2->DeviceProtocol))
                        {
                            *DeviceHandle = UsbIoBuffer[Index];
                            // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path
                            *NewDevicePath = AppendDevicePath (UsbIoDevicePath, NextDevicePathNode(RemovableDevicePath));
                            return EFI_SUCCESS;
                        }
                    }
                }
                TmpDevicePath = NextDevicePathNode (TmpDevicePath);
            }

        }
    }

    return EFI_NOT_FOUND;
}
Beispiel #23
0
EFI_STATUS
ImcControlEntry (
  IN       EFI_HANDLE         ImageHandle,
  IN       EFI_SYSTEM_TABLE   *SystemTable
  )

{
  EFI_STATUS                      Status;
  BOOLEAN                         InSmm;
  EFI_SMM_BASE_PROTOCOL           *SmmBase;
  EFI_LOADED_IMAGE_PROTOCOL       *LoadedImage;
  EFI_DEVICE_PATH_PROTOCOL        *ImageDevicePath;
  EFI_DEVICE_PATH_PROTOCOL        *CompleteFilePath;
  FCH_INIT_PROTOCOL               *AmdFchInit;
  EFI_HANDLE                      SmmImageHandle;

  //
  // Initialize EFI library
  //
  InSmm    = FALSE;
  gST      = SystemTable;
  gBS      = SystemTable->BootServices;

  Status = gBS->LocateProtocol (
                  &gEfiSmmBaseProtocolGuid,
                  NULL,
                  &SmmBase
                  );

  if (EFI_ERROR (Status)) {
    return Status;
  }
  SmmBase->GetSmstLocation (
             SmmBase,
             &mSmst
             );
  mSmmIo = &mSmst->SmmIo;
  SmmBase->InSmm (
             SmmBase,
             &InSmm
             );


  if (!InSmm) {
    //
    // Not in SMM. Load this driver's image into SMRAM
    //
    if (ImageHandle != NULL) {
      Status = gBS->HandleProtocol (
                      ImageHandle,
                      &gEfiLoadedImageProtocolGuid,
                      &LoadedImage
                      );
      if (EFI_ERROR (Status)) {
        return Status;
      }

      Status = gBS->HandleProtocol (
                      LoadedImage->DeviceHandle,
                      &gEfiDevicePathProtocolGuid,
                      (VOID*) &ImageDevicePath
                      );

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

      CompleteFilePath = AppendDevicePath (
                           ImageDevicePath,
                           LoadedImage->FilePath
                           );

      // Load the image in memory to SMRAM, this automatically triggers SMI
      SmmBase->Register (
                 SmmBase,
                 CompleteFilePath,
                 NULL,
                 0,
                 &SmmImageHandle,
                 FALSE
                 );
    }
  } else {
    //
    // We're now in SMM!
    //
    Status = gBS->LocateProtocol (
                    &gFchInitProtocolGuid,
                    NULL,
                    &AmdFchInit
                    );
    if (!EFI_ERROR (Status)) {
      mImcThermalEnable = AmdFchInit->FchPolicy.Imc.EcStruct.IMCFUNSupportBitMap;
    } else {
      return EFI_ABORTED;
    }

    Status = ImcControlSmmRegister ();
    return Status;

  }
  return Status;
}
Beispiel #24
0
/*----------------------------------------------------------------------------------------*/
EFI_STATUS
FchSmmDispatcherEntry (
  IN       EFI_HANDLE         ImageHandle,
  IN       EFI_SYSTEM_TABLE   *SystemTable
  )
{
  EFI_STATUS                    Status;
  EFI_HANDLE                    Handle;
  BOOLEAN                       InSmm;
  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
  EFI_DEVICE_PATH_PROTOCOL      *ImageDevicePath;
  EFI_DEVICE_PATH_PROTOCOL      *CompleteFilePath;

// Initialize Global Variable
  gST = SystemTable;
  gBS = SystemTable->BootServices;
  gRT = SystemTable->RuntimeServices;

  InSmm = FALSE;

  Status = gBS->LocateProtocol (
                  &gEfiSmmBaseProtocolGuid,
                  NULL,
                  &mSmmBasePtr
                  );

  ASSERT_EFI_ERROR (Status);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  mSmmBasePtr->InSmm (mSmmBasePtr, &InSmm);
  mSmmBasePtr->GetSmstLocation (mSmmBasePtr, &mSmstPtr);

  if (!InSmm) {
    Status = gBS->HandleProtocol (
                    ImageHandle,
                    &gEfiLoadedImageProtocolGuid,
                    &LoadedImage
                    );

    if (EFI_ERROR (Status)) {
      return Status;
    }
    Status = gBS->HandleProtocol (
                    LoadedImage->DeviceHandle,
                    &gEfiDevicePathProtocolGuid,
                    (VOID*)&ImageDevicePath
                    );

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

    CompleteFilePath = AppendDevicePath (
                         ImageDevicePath,
                         LoadedImage->FilePath
                         );

    Status = mSmmBasePtr->Register (
                            mSmmBasePtr,
                            CompleteFilePath,
                            NULL,
                            0,
                            &Handle,
                            FALSE
                            );

    ASSERT_EFI_ERROR (Status);

  } else {
    Status = gBS->InstallMultipleProtocolInterfaces (
                    &ImageHandle,
                    &gFchSmmSxDispatchProtocolGuid,
                    &gFchSmmSxDispatchProtocol,
                    &gFchSmmSwDispatchProtocolGuid,
                    &gFchSmmSwDispatchProtocol,
                    &gFchSmmPwrBtnDispatchProtocolGuid,
                    &gFchSmmPwrBtnDispatchProtocol,
                    &gFchSmmIoTrapDispatchProtocolGuid,
                    &gFchSmmIoTrapDispatchProtocol,
                    &gFchSmmPeriodicalDispatchProtocolGuid,
                    &gFchSmmPeriodicalDispatchProtocol,
                    &gFchSmmGpeDispatchProtocolGuid,
                    &gFchSmmGpeDispatchProtocol,
                    &gFchSmmUsbDispatchProtocolGuid,
                    &gFchSmmUsbDispatchProtocol,
                    &gFchSmmMiscDispatchProtocolGuid,
                    &gFchSmmMiscDispatchProtocol,
                    NULL
                    );

    Status = gBS->InstallMultipleProtocolInterfaces (
                    &ImageHandle,
                    &gFchSmmSwDispatch2ProtocolGuid,
                    &gFchSmmSwDispatch2Protocol,
                    &gFchSmmSxDispatch2ProtocolGuid,
                    &gFchSmmSxDispatch2Protocol,
                    &gFchSmmUsbDispatch2ProtocolGuid,
                    &gFchSmmUsbDispatch2Protocol,
                    &gFchSmmPwrBtnDispatch2ProtocolGuid,
                    &gFchSmmPwrBtnDispatch2Protocol,
                    NULL
                    );

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

    Status = mSmmBasePtr->RegisterCallback (
                            mSmmBasePtr,
                            ImageHandle,
                            FchSmmDispatchHandler,
                            FALSE,
                            FALSE
                            );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    Status = mSmmBasePtr->SmmAllocatePool (
                            mSmmBasePtr,
                            EfiRuntimeServicesData,
                            sizeof (FCH_SMM_SW_NODE),
                            &HeadFchSmmSwNodePtr
                            );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    HeadFchSmmSwNodePtr->FchSwNodePtr = NULL;
    HeadFchSmmSwNodePtr->CallBackFunction = NULL;
    HeadFchSmmSwNodePtr->CallBack2Function = NULL;
    HeadFchSmmSwNodePtr->Context.AmdSwValue = 0;
    HeadFchSmmSwNodePtr->DispatchHandle = NULL;

    Status = mSmmBasePtr->SmmAllocatePool (
                            mSmmBasePtr,
                            EfiRuntimeServicesData,
                            sizeof (FCH_SMM_SX_NODE),
                            &HeadFchSmmSxNodePtr
                            );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    HeadFchSmmSxNodePtr->FchSxNodePtr = NULL;
    HeadFchSmmSxNodePtr->CallBackFunction = NULL;
    HeadFchSmmSxNodePtr->CallBack2Function = NULL;
    HeadFchSmmSxNodePtr->Context.Type = 0;
    HeadFchSmmSxNodePtr->Context.Phase = 0;
    HeadFchSmmSxNodePtr->DispatchHandle = NULL;

    Status = mSmmBasePtr->SmmAllocatePool (
                            mSmmBasePtr,
                            EfiRuntimeServicesData,
                            sizeof (FCH_SMM_PWRBTN_NODE),
                            &HeadFchSmmPwrBtnNodePtr
                            );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    HeadFchSmmPwrBtnNodePtr->FchPwrBtnNodePtr = NULL;
    HeadFchSmmPwrBtnNodePtr->CallBackFunction = NULL;
    HeadFchSmmPwrBtnNodePtr->CallBack2Function = NULL;
    HeadFchSmmPwrBtnNodePtr->DispatchHandle = NULL;

    Status = mSmmBasePtr->SmmAllocatePool (
                            mSmmBasePtr,
                            EfiRuntimeServicesData,
                            sizeof (FCH_SMM_PERIODICAL_NODE),
                            &HeadFchSmmPeriodicalNodePtr
                            );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    HeadFchSmmPeriodicalNodePtr->FchPeriodicalNodePtr = NULL;
    HeadFchSmmPeriodicalNodePtr->CallBackFunction = NULL;
    HeadFchSmmPeriodicalNodePtr->DispatchHandle = NULL;

    Status = mSmmBasePtr->SmmAllocatePool (
                            mSmmBasePtr,
                            EfiRuntimeServicesData,
                            sizeof (FCH_SMM_GPE_NODE),
                            &HeadFchSmmGpeNodePtr
                            );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    HeadFchSmmGpeNodePtr->FchGpeNodePtr = NULL;
    HeadFchSmmGpeNodePtr->CallBackFunction = NULL;
    HeadFchSmmGpeNodePtr->Context.AmdGpeNum = 0xffff;
    HeadFchSmmGpeNodePtr->DispatchHandle = NULL;

    Status = mSmmBasePtr->SmmAllocatePool (
                            mSmmBasePtr,
                            EfiRuntimeServicesData,
                            sizeof (FCH_SMM_USB_NODE),
                            &HeadFchSmmUsbNodePtr
                            );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    HeadFchSmmUsbNodePtr->FchUsbNodePtr = NULL;
    HeadFchSmmUsbNodePtr->CallBackFunction = NULL;
    HeadFchSmmUsbNodePtr->CallBack2Function = NULL;
    HeadFchSmmUsbNodePtr->Context.Type = Wake;
    HeadFchSmmUsbNodePtr->Context.Device = NULL;
    HeadFchSmmUsbNodePtr->Context.Order = 0xFF;
    HeadFchSmmUsbNodePtr->DispatchHandle = NULL;

    Status = mSmmBasePtr->SmmAllocatePool (
                            mSmmBasePtr,
                            EfiRuntimeServicesData,
                            sizeof (FCH_SMM_MISC_NODE),
                            &HeadFchSmmMiscNodePtr
                            );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    HeadFchSmmMiscNodePtr->FchMiscNodePtr = NULL;
    HeadFchSmmMiscNodePtr->CallBackFunction = NULL;
    HeadFchSmmMiscNodePtr->Context.SmiStatusReg = 0;
    HeadFchSmmMiscNodePtr->Context.SmiStatusBit = 0;
    HeadFchSmmMiscNodePtr->DispatchHandle = NULL;


    Status = mSmmBasePtr->SmmAllocatePool (
                            mSmmBasePtr,
                            EfiRuntimeServicesData,
                            sizeof (FCH_SMM_SW_CONTEXT),
                            &EfiSmmSwContext
                            );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    EfiSmmSwContext->SwSmiCpuIndex = 0;
    EfiSmmSwContext->CommandPort = 0;
    EfiSmmSwContext->DataPort = 0;

    Status = mSmmBasePtr->SmmAllocatePool (
                            mSmmBasePtr,
                            EfiRuntimeServicesData,
                            sizeof (FCH_SMM_COMMUNICATION_BUFFER),
                            &CommunicationBufferPtr
                            );
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }

  {
    UINT32  SmmDispatcherData32;
    UINT32  SmmDispatcherIndex;

  //
  // Clear all handled SMI status bit
  //
    for (SmmDispatcherIndex = 0; SmmDispatcherIndex < NumOfDispatcherTableEntry; SmmDispatcherIndex++ ) {
      SmmDispatcherData32 = ACPIMMIO32 (ACPI_MMIO_BASE + SMI_BASE + FchSmmDispatcherTable[SmmDispatcherIndex].StatusReg);
      SmmDispatcherData32 &= FchSmmDispatcherTable[SmmDispatcherIndex].SmiStatusBit;
      ACPIMMIO32 (ACPI_MMIO_BASE + SMI_BASE + FchSmmDispatcherTable[SmmDispatcherIndex].StatusReg) = SmmDispatcherData32;
    }
  //
  // Clear SmiEnB and Set EOS
  //
    SmmDispatcherData32 = ACPIMMIO32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REG98);
    SmmDispatcherData32 &= ~(BIT31);
    SmmDispatcherData32 |= BIT28;
    ACPIMMIO32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REG98) = SmmDispatcherData32;
  }

  return Status;
}
Beispiel #25
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;
}