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; }
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; }
/** 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; }
EFIAPI AppendDevicePathProtocolInterface ( IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath ) { return AppendDevicePath (FirstDevicePath, SecondDevicePath); }
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); }
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; }
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; }
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; }
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; }
/********************************************************************************* * 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; }
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; }
/** 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; }
/** 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; }
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; }
/** 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; }
/******************************************************************************** * 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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
/*----------------------------------------------------------------------------------------*/ 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; }
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; }