/** Writes a buffer to variable storage space, in the working block. This function writes a buffer to variable storage space into a firmware volume block device. The destination is specified by parameter VariableBase. Fault Tolerant Write protocol is used for writing. @param VariableBase Base address of variable to write @param Buffer Point to the data buffer. @param BufferSize The number of bytes of the data Buffer. @retval EFI_SUCCESS The function completed successfully. @retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol. @retval EFI_ABORTED The function could not complete successfully. **/ EFI_STATUS FtwVariableSpace ( IN EFI_PHYSICAL_ADDRESS VariableBase, IN UINT8 *Buffer, IN UINTN BufferSize ) { EFI_STATUS Status; EFI_HANDLE FvbHandle; EFI_LBA VarLba; UINTN VarOffset; UINT8 *FtwBuffer; UINTN FtwBufferSize; EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol; // // Locate fault tolerant write protocol. // Status = GetFtwProtocol((VOID **) &FtwProtocol); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } // // Locate Fvb handle by address. // Status = GetFvbInfoByAddress (VariableBase, &FvbHandle, NULL); if (EFI_ERROR (Status)) { return Status; } // // Get LBA and Offset by address. // Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset); if (EFI_ERROR (Status)) { return EFI_ABORTED; } // // Prepare for the variable data. // FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size; FtwBuffer = AllocatePool (FtwBufferSize); if (FtwBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } SetMem (FtwBuffer, FtwBufferSize, (UINT8) 0xff); CopyMem (FtwBuffer, Buffer, BufferSize); // // FTW write record. // Status = FtwProtocol->Write ( FtwProtocol, VarLba, // LBA VarOffset, // Offset FtwBufferSize, // NumBytes NULL, // PrivateData NULL FvbHandle, // Fvb Handle FtwBuffer // write buffer ); FreePool (FtwBuffer); return Status; }
EFI_STATUS BBTestQueryCapsuleCapabilitiesConformanceTest ( IN EFI_BB_TEST_PROTOCOL *This, IN VOID *ClientInterface, IN EFI_TEST_LEVEL TestLevel, IN EFI_HANDLE SupportHandle ) { EFI_STATUS Status; EFI_STANDARD_TEST_LIBRARY_PROTOCOL *StandardLib; EFI_TEST_ASSERTION AssertionType; UINT8 *AllocatedBuffer; EFI_CAPSULE_HEADER *CapsuleHeaderArray[2]; EFI_RESET_TYPE ResetType; // // Get the Standard Library Interface // Status = gtBS->HandleProtocol ( SupportHandle, &gEfiStandardTestLibraryGuid, &StandardLib ); if (EFI_ERROR(Status)) { return Status; } if (FALSE == CheckBBTestCanRunAndRecordAssertion( StandardLib, L"RT.QueryCapsuleCapabilities_Conf - QueryCapsuleCapabilities_Conf it's not Supported in EFI", __FILE__, (UINTN)__LINE__ )) { return EFI_SUCCESS; } AllocatedBuffer = (UINT8 *)AllocatePool (sizeof(EFI_CAPSULE_HEADER)); if (AllocatedBuffer == NULL) { StandardLib->RecordAssertion ( StandardLib, EFI_TEST_ASSERTION_FAILED, gTestGenericFailureGuid, L"RT.QueryCapsuleCapabilities_Conf - Allocate zero pool for EFI_CAPSULE_HEADER", L"%a:%d,Status - %r", __FILE__, (UINTN)__LINE__, Status ); return Status; } CapsuleHeaderArray[0] = (EFI_CAPSULE_HEADER *) (UINTN)AllocatedBuffer; CapsuleHeaderArray[0]->CapsuleGuid = mEfiCapsuleHeaderGuid; CapsuleHeaderArray[0]->HeaderSize = sizeof(EFI_CAPSULE_HEADER); CapsuleHeaderArray[0]->CapsuleImageSize = sizeof(EFI_CAPSULE_HEADER); CapsuleHeaderArray[1] = NULL; // When the flag is CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE and CAPSULE_FLAGS_PERSIST_ACROSS_RESET, platform will ignore the CapsuleGuid CapsuleHeaderArray[0]->Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE; Status = gtRT->QueryCapsuleCapabilities( CapsuleHeaderArray, 1, NULL, //invalid &ResetType); if ((Status == EFI_INVALID_PARAMETER) || (Status == EFI_UNSUPPORTED)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gMiscRuntimeServicesBBTestConformanceAssertionGuid004, L"RT.QueryCapsuleCapabilities - invoke QueryCapsuleCapabilities with invalid MaxiumCapsuleSize", L"%a:%d:Status - %r", __FILE__, (UINTN)__LINE__, Status ); FreePool (AllocatedBuffer); return EFI_SUCCESS; }
EFI_STATUS FileOpen ( IN EFI_FILE *File, OUT EFI_FILE **NewHandle, IN CHAR16 *FileName, IN UINT64 OpenMode, IN UINT64 Attributes ) { SEMIHOST_FCB *FileFcb = NULL; EFI_STATUS Status = EFI_SUCCESS; UINTN SemihostHandle; CHAR8 *AsciiFileName; UINT32 SemihostMode; BOOLEAN IsRoot; if ((FileName == NULL) || (NewHandle == NULL)) { return EFI_INVALID_PARAMETER; } // Semihost interface requires ASCII filenames AsciiFileName = AllocatePool ((StrLen (FileName) + 1) * sizeof (CHAR8)); if (AsciiFileName == NULL) { return EFI_OUT_OF_RESOURCES; } UnicodeStrToAsciiStr (FileName, AsciiFileName); if ((AsciiStrCmp (AsciiFileName, "\\") == 0) || (AsciiStrCmp (AsciiFileName, "/") == 0) || (AsciiStrCmp (AsciiFileName, "") == 0) || (AsciiStrCmp (AsciiFileName, ".") == 0)) { // Opening '/', '\', '.', or the NULL pathname is trying to open the root directory IsRoot = TRUE; // Root directory node doesn't have a name. FreePool (AsciiFileName); AsciiFileName = NULL; } else { // Translate EFI_FILE_MODE into Semihosting mode if (OpenMode & EFI_FILE_MODE_WRITE) { SemihostMode = SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY; } else if (OpenMode & EFI_FILE_MODE_READ) { SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY; } else { return EFI_UNSUPPORTED; } // Add the creation flag if necessary if (OpenMode & EFI_FILE_MODE_CREATE) { SemihostMode |= SEMIHOST_FILE_MODE_CREATE; } // Call the semihosting interface to open the file. Status = SemihostFileOpen (AsciiFileName, SemihostMode, &SemihostHandle); if (EFI_ERROR(Status)) { return Status; } IsRoot = FALSE; } // Allocate a control block and fill it FileFcb = AllocateFCB (); if (FileFcb == NULL) { return EFI_OUT_OF_RESOURCES; } FileFcb->FileName = AsciiFileName; FileFcb->SemihostHandle = SemihostHandle; FileFcb->Position = 0; FileFcb->IsRoot = IsRoot; InsertTailList (&gFileList, &FileFcb->Link); *NewHandle = &FileFcb->File; return Status; }
/** Install child handles if the Handle supports MBR format. @param[in] This Calling context. @param[in] Handle Parent Handle. @param[in] DiskIo Parent DiskIo interface. @param[in] BlockIo Parent BlockIo interface. @param[in] BlockIo2 Parent BlockIo2 interface. @param[in] DevicePath Parent Device Path. @retval EFI_SUCCESS A child handle was added. @retval EFI_MEDIA_CHANGED Media change was detected. @retval Others MBR partition was not found. **/ EFI_STATUS PartitionInstallMbrChildHandles ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_STATUS Status; MASTER_BOOT_RECORD *Mbr; UINT32 ExtMbrStartingLba; UINTN Index; HARDDRIVE_DEVICE_PATH HdDev; HARDDRIVE_DEVICE_PATH ParentHdDev; EFI_STATUS Found; UINT32 PartitionNumber; EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; EFI_DEVICE_PATH_PROTOCOL *LastDevicePathNode; UINT32 BlockSize; UINT32 MediaId; EFI_LBA LastBlock; Found = EFI_NOT_FOUND; BlockSize = BlockIo->Media->BlockSize; MediaId = BlockIo->Media->MediaId; LastBlock = BlockIo->Media->LastBlock; VBoxLogFlowFuncMarkDP(DevicePath); Mbr = AllocatePool (BlockSize); if (Mbr == NULL) { return Found; } Status = DiskIo->ReadDisk ( DiskIo, MediaId, 0, BlockSize, Mbr ); if (EFI_ERROR (Status)) { Found = Status; goto Done; } if (!PartitionValidMbr (Mbr, LastBlock)) { goto Done; } // // We have a valid mbr - add each partition // // // Get starting and ending LBA of the parent block device. // LastDevicePathNode = NULL; ZeroMem (&ParentHdDev, sizeof (ParentHdDev)); DevicePathNode = DevicePath; while (!IsDevicePathEnd (DevicePathNode)) { LastDevicePathNode = DevicePathNode; DevicePathNode = NextDevicePathNode (DevicePathNode); } if (LastDevicePathNode != NULL) { if (DevicePathType (LastDevicePathNode) == MEDIA_DEVICE_PATH && DevicePathSubType (LastDevicePathNode) == MEDIA_HARDDRIVE_DP ) { CopyMem (&ParentHdDev, LastDevicePathNode, sizeof (ParentHdDev)); } else { LastDevicePathNode = NULL; } } PartitionNumber = 1; ZeroMem (&HdDev, sizeof (HdDev)); HdDev.Header.Type = MEDIA_DEVICE_PATH; HdDev.Header.SubType = MEDIA_HARDDRIVE_DP; SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev)); HdDev.MBRType = MBR_TYPE_PCAT; HdDev.SignatureType = SIGNATURE_TYPE_MBR; if (LastDevicePathNode == NULL) { // // This is a MBR, add each partition // for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) { if (Mbr->Partition[Index].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index].SizeInLBA) == 0) { // // Don't use null MBR entries // continue; } if (Mbr->Partition[Index].OSIndicator == PMBR_GPT_PARTITION) { // // This is the guard MBR for the GPT. If you ever see a GPT disk with zero partitions you can get here. // We can not produce an MBR BlockIo for this device as the MBR spans the GPT headers. So formating // this BlockIo would corrupt the GPT structures and require a recovery that would corrupt the format // that corrupted the GPT partition. // continue; } HdDev.PartitionNumber = PartitionNumber ++; HdDev.PartitionStart = UNPACK_UINT32 (Mbr->Partition[Index].StartingLBA); HdDev.PartitionSize = UNPACK_UINT32 (Mbr->Partition[Index].SizeInLBA); CopyMem (HdDev.Signature, &(Mbr->UniqueMbrSignature[0]), sizeof (Mbr->UniqueMbrSignature)); Status = PartitionInstallChildHandle ( This, Handle, DiskIo, BlockIo, BlockIo2, DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &HdDev, HdDev.PartitionStart, HdDev.PartitionStart + HdDev.PartitionSize - 1, MBR_SIZE, (BOOLEAN) (Mbr->Partition[Index].OSIndicator == EFI_PARTITION) ); if (!EFI_ERROR (Status)) { Found = EFI_SUCCESS; } } } else { // // It's an extended partition. Follow the extended partition // chain to get all the logical drives // ExtMbrStartingLba = 0; do { Status = DiskIo->ReadDisk ( DiskIo, MediaId, MultU64x32 (ExtMbrStartingLba, BlockSize), BlockSize, Mbr ); if (EFI_ERROR (Status)) { Found = Status; goto Done; } if (UNPACK_UINT32 (Mbr->Partition[0].SizeInLBA) == 0) { break; } if ((Mbr->Partition[0].OSIndicator == EXTENDED_DOS_PARTITION) || (Mbr->Partition[0].OSIndicator == EXTENDED_WINDOWS_PARTITION)) { ExtMbrStartingLba = UNPACK_UINT32 (Mbr->Partition[0].StartingLBA); continue; } HdDev.PartitionNumber = PartitionNumber ++; HdDev.PartitionStart = UNPACK_UINT32 (Mbr->Partition[0].StartingLBA) + ExtMbrStartingLba + ParentHdDev.PartitionStart; HdDev.PartitionSize = UNPACK_UINT32 (Mbr->Partition[0].SizeInLBA); if ((HdDev.PartitionStart + HdDev.PartitionSize - 1 >= ParentHdDev.PartitionStart + ParentHdDev.PartitionSize) || (HdDev.PartitionStart <= ParentHdDev.PartitionStart)) { break; } // // The signature in EBR(Extended Boot Record) should always be 0. // *((UINT32 *) &HdDev.Signature[0]) = 0; Status = PartitionInstallChildHandle ( This, Handle, DiskIo, BlockIo, BlockIo2, DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &HdDev, HdDev.PartitionStart - ParentHdDev.PartitionStart, HdDev.PartitionStart - ParentHdDev.PartitionStart + HdDev.PartitionSize - 1, MBR_SIZE, (BOOLEAN) (Mbr->Partition[0].OSIndicator == EFI_PARTITION) ); if (!EFI_ERROR (Status)) { Found = EFI_SUCCESS; } if ((Mbr->Partition[1].OSIndicator != EXTENDED_DOS_PARTITION) && (Mbr->Partition[1].OSIndicator != EXTENDED_WINDOWS_PARTITION) ) { break; } ExtMbrStartingLba = UNPACK_UINT32 (Mbr->Partition[1].StartingLBA); // // Don't allow partition to be self referencing // if (ExtMbrStartingLba == 0) { break; } } while (ExtMbrStartingLba < ParentHdDev.PartitionSize); } Done: FreePool (Mbr); return Found; }
/** Worker function that truncate a file specified by its name to a given size. @param[in] FileName The Null-terminated string of the name of the file to be opened. @param[in] Size The target size for the file. @retval EFI_SUCCESS The file was truncated. @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed. **/ STATIC EFI_STATUS TruncateFile ( IN CHAR8 *FileName, IN UINTN Size ) { EFI_STATUS Status; RETURN_STATUS Return; UINTN FileHandle; UINT8 *Buffer; UINTN Remaining; UINTN Read; UINTN ToRead; Status = EFI_DEVICE_ERROR; FileHandle = 0; Buffer = NULL; Return = SemihostFileOpen ( FileName, SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY, &FileHandle ); if (RETURN_ERROR (Return)) { goto Error; } Buffer = AllocatePool (Size); if (Buffer == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error; } Read = 0; Remaining = Size; while (Remaining > 0) { ToRead = Remaining; Return = SemihostFileRead (FileHandle, &ToRead, Buffer + Read); if (RETURN_ERROR (Return)) { goto Error; } Remaining -= ToRead; Read += ToRead; } Return = SemihostFileClose (FileHandle); FileHandle = 0; if (RETURN_ERROR (Return)) { goto Error; } Return = SemihostFileOpen ( FileName, SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY, &FileHandle ); if (RETURN_ERROR (Return)) { goto Error; } if (Size > 0) { Return = SemihostFileWrite (FileHandle, &Size, Buffer); if (RETURN_ERROR (Return)) { goto Error; } } Status = EFI_SUCCESS; Error: if (FileHandle != 0) { SemihostFileClose (FileHandle); } if (Buffer != NULL) { FreePool (Buffer); } return (Status); }
/** Set or update a HTTP header with the field name and corresponding value. @param[in] HttpIoHeader Point to the HTTP header holder. @param[in] FieldName Null terminated string which describes a field name. @param[in] FieldValue Null terminated string which describes the corresponding field value. @retval EFI_SUCCESS The HTTP header has been set or updated. @retval EFI_INVALID_PARAMETER Any input parameter is invalid. @retval EFI_OUT_OF_RESOURCES Insufficient resource to complete the operation. @retval Other Unexpected error happened. **/ EFI_STATUS HttpBootSetHeader ( IN HTTP_IO_HEADER *HttpIoHeader, IN CHAR8 *FieldName, IN CHAR8 *FieldValue ) { EFI_HTTP_HEADER *Header; UINTN StrSize; CHAR8 *NewFieldValue; if (HttpIoHeader == NULL || FieldName == NULL || FieldValue == NULL) { return EFI_INVALID_PARAMETER; } Header = HttpFindHeader (HttpIoHeader->HeaderCount, HttpIoHeader->Headers, FieldName); if (Header == NULL) { // // Add a new header. // if (HttpIoHeader->HeaderCount >= HttpIoHeader->MaxHeaderCount) { return EFI_OUT_OF_RESOURCES; } Header = &HttpIoHeader->Headers[HttpIoHeader->HeaderCount]; StrSize = AsciiStrSize (FieldName); Header->FieldName = AllocatePool (StrSize); if (Header->FieldName == NULL) { return EFI_OUT_OF_RESOURCES; } CopyMem (Header->FieldName, FieldName, StrSize); Header->FieldName[StrSize -1] = '\0'; StrSize = AsciiStrSize (FieldValue); Header->FieldValue = AllocatePool (StrSize); if (Header->FieldValue == NULL) { FreePool (Header->FieldName); return EFI_OUT_OF_RESOURCES; } CopyMem (Header->FieldValue, FieldValue, StrSize); Header->FieldValue[StrSize -1] = '\0'; HttpIoHeader->HeaderCount++; } else { // // Update an existing one. // StrSize = AsciiStrSize (FieldValue); NewFieldValue = AllocatePool (StrSize); if (NewFieldValue == NULL) { return EFI_OUT_OF_RESOURCES; } CopyMem (NewFieldValue, FieldValue, StrSize); NewFieldValue[StrSize -1] = '\0'; if (Header->FieldValue != NULL) { FreePool (Header->FieldValue); } Header->FieldValue = NewFieldValue; } return EFI_SUCCESS; }
EFI_STATUS BootMenuUpdateBootOption ( IN LIST_ENTRY *BootOptionsList ) { EFI_STATUS Status; BDS_LOAD_OPTION_ENTRY *BootOptionEntry; BDS_LOAD_OPTION *BootOption; BDS_LOAD_OPTION_SUPPORT* DeviceSupport; ARM_BDS_LOADER_ARGUMENTS* BootArguments; CHAR16 BootDescription[BOOT_DEVICE_DESCRIPTION_MAX]; CHAR8 CmdLine[BOOT_DEVICE_OPTION_MAX]; CHAR16 UnicodeCmdLine[BOOT_DEVICE_OPTION_MAX]; EFI_DEVICE_PATH *DevicePath; EFI_DEVICE_PATH *TempInitrdPath; ARM_BDS_LOADER_TYPE BootType; ARM_BDS_LOADER_OPTIONAL_DATA* LoaderOptionalData; ARM_BDS_LINUX_ARGUMENTS* LinuxArguments; EFI_DEVICE_PATH *InitrdPathNodes; EFI_DEVICE_PATH *InitrdPath; UINTN InitrdSize; UINTN CmdLineSize; BOOLEAN InitrdSupport; UINT8* OptionalData; UINTN OptionalDataSize; BOOLEAN IsPrintable; BOOLEAN IsUnicode; DisplayBootOptions (BootOptionsList); Status = SelectBootOption (BootOptionsList, UPDATE_BOOT_ENTRY, &BootOptionEntry); if (EFI_ERROR (Status)) { return Status; } BootOption = BootOptionEntry->BdsLoadOption; // Get the device support for this Boot Option Status = BootDeviceGetDeviceSupport (BootOption->FilePathList, &DeviceSupport); if (EFI_ERROR(Status)) { Print(L"Not possible to retrieve the supported device for the update\n"); return EFI_UNSUPPORTED; } Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application or the kernel", &DevicePath); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } if (DeviceSupport->RequestBootType) { Status = BootDeviceGetType (DevicePath, &BootType, &BootOption->Attributes); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } } LoaderOptionalData = BootOption->OptionalData; if (LoaderOptionalData != NULL) { BootType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((UINT32 *)(&LoaderOptionalData->Header.LoaderType)); } else { BootType = BDS_LOADER_EFI_APPLICATION; } if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { LinuxArguments = &LoaderOptionalData->Arguments.LinuxArguments; CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize); InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize); if (InitrdSize > 0) { Print(L"Keep the initrd: "); } else { Print(L"Add an initrd: "); } Status = GetHIInputBoolean (&InitrdSupport); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } if (InitrdSupport) { if (InitrdSize > 0) { // Case we update the initrd device path Status = DeviceSupport->UpdateDevicePathNode ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize), L"initrd", &InitrdPath); if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) {// EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd Status = EFI_ABORTED; goto EXIT; } InitrdSize = GetDevicePathSize (InitrdPath); } else { // Case we create the initrd device path Status = DeviceSupport->CreateDevicePathNode (L"initrd", &InitrdPathNodes); if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd Status = EFI_ABORTED; goto EXIT; } if (InitrdPathNodes != NULL) { // Duplicate Linux kernel Device Path TempInitrdPath = DuplicateDevicePath (BootOption->FilePathList); // Replace Linux kernel Node by EndNode SetDevicePathEndNode (GetLastDevicePathNode (TempInitrdPath)); // Append the Device Path to the selected device path InitrdPath = AppendDevicePath (TempInitrdPath, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes); FreePool (TempInitrdPath); // Free the InitrdPathNodes created by Support->CreateDevicePathNode() FreePool (InitrdPathNodes); if (InitrdPath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto EXIT; } InitrdSize = GetDevicePathSize (InitrdPath); } else { InitrdPath = NULL; } } } else { InitrdSize = 0; } Print(L"Arguments to pass to the binary: "); if (CmdLineSize > 0) { AsciiStrnCpy (CmdLine, (CONST CHAR8*)(LinuxArguments + 1), sizeof (CmdLine)); CmdLine[sizeof (CmdLine) - 1] = '\0'; } else { CmdLine[0] = '\0'; } Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } CmdLineSize = AsciiStrSize (CmdLine); OptionalDataSize = sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize; BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (OptionalDataSize); BootArguments->LinuxArguments.CmdLineSize = CmdLineSize; BootArguments->LinuxArguments.InitrdSize = InitrdSize; CopyMem (&BootArguments->LinuxArguments + 1, CmdLine, CmdLineSize); CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize); OptionalData = (UINT8*)BootArguments; } else { Print (L"Arguments to pass to the EFI Application: "); if (BootOption->OptionalDataSize > 0) { IsPrintable = IsPrintableString (BootOption->OptionalData, &IsUnicode); if (IsPrintable) { // // The size in bytes of the string, final zero included, should // be equal to or at least lower than "BootOption->OptionalDataSize" // and the "IsPrintableString()" has already tested that the length // in number of characters is smaller than BOOT_DEVICE_OPTION_MAX, // final '\0' included. We can thus copy the string for editing // using "CopyMem()". Furthermore, note that in the case of an Unicode // string "StrnCpy()" and "StrCpy()" can not be used to copy the // string because the data pointed to by "BootOption->OptionalData" // is not necessarily 2-byte aligned. // if (IsUnicode) { CopyMem ( UnicodeCmdLine, BootOption->OptionalData, MIN (sizeof (UnicodeCmdLine), BootOption->OptionalDataSize) ); } else { CopyMem ( CmdLine, BootOption->OptionalData, MIN (sizeof (CmdLine), BootOption->OptionalDataSize) ); } } } else { UnicodeCmdLine[0] = L'\0'; IsPrintable = TRUE; IsUnicode = TRUE; } // We do not request arguments for OptionalData that cannot be printed if (IsPrintable) { if (IsUnicode) { Status = EditHIInputStr (UnicodeCmdLine, BOOT_DEVICE_OPTION_MAX); if (EFI_ERROR (Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } OptionalData = (UINT8*)UnicodeCmdLine; OptionalDataSize = StrSize (UnicodeCmdLine); } else { Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX); if (EFI_ERROR (Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } OptionalData = (UINT8*)CmdLine; OptionalDataSize = AsciiStrSize (CmdLine); } } else { // We keep the former OptionalData OptionalData = BootOption->OptionalData; OptionalDataSize = BootOption->OptionalDataSize; } } Print(L"Description for this new Entry: "); StrnCpy (BootDescription, BootOption->Description, BOOT_DEVICE_DESCRIPTION_MAX); Status = EditHIInputStr (BootDescription, BOOT_DEVICE_DESCRIPTION_MAX); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } // Update the entry Status = BootOptionUpdate (BootOption, BootOption->Attributes, BootDescription, DevicePath, BootType, OptionalData, OptionalDataSize); FREE_DEVICE_PATH: FreePool (DevicePath); EXIT: if (Status == EFI_ABORTED) { Print(L"\n"); } return Status; }
// // TDS 3.4.3 // EFI_STATUS DevicePathUtilitiesAppendDevicePathConformanceTest ( IN EFI_BB_TEST_PROTOCOL *This, IN VOID *ClientInterface, IN EFI_TEST_LEVEL TestLevel, IN EFI_HANDLE SupportHandle ) { EFI_STANDARD_TEST_LIBRARY_PROTOCOL *StandardLib; EFI_STATUS Status; EFI_DEVICE_PATH_UTILITIES_PROTOCOL *DevicePathUtilities; EFI_TEST_ASSERTION AssertionType; EFI_DEVICE_PATH_PROTOCOL *pDevicePath1; EFI_DEVICE_PATH_PROTOCOL *pDevicePath2; EFI_DEVICE_PATH_PROTOCOL *pDevicePath3; EFI_DEVICE_PATH_PROTOCOL *pDevicePath4; UINTN DevicePathLen1; UINTN DevicePathLen2; UINTN DevicePathLen3; // // Get the Standard Library Interface // Status = gtBS->HandleProtocol ( SupportHandle, &gEfiStandardTestLibraryGuid, &StandardLib ); if (EFI_ERROR (Status)) { return Status; } DevicePathUtilities = (EFI_DEVICE_PATH_UTILITIES_PROTOCOL *) ClientInterface; // // TDS 3.4.3.2.1 // pDevicePath1 = (EFI_DEVICE_PATH *) AllocatePool (END_DEVICE_PATH_LENGTH); SetDevicePathEndNode (pDevicePath1); pDevicePath3 = DevicePathUtilities->CreateDeviceNode (USBNodeType, USBNodeSubType, USBNodeLength); pDevicePath4 = DevicePathUtilities->AppendDeviceNode (pDevicePath1, pDevicePath3); FreePool (pDevicePath1); FreePool (pDevicePath3); DevicePathLen2 = DevicePathUtilities->GetDevicePathSize (pDevicePath4); pDevicePath1 = DevicePathUtilities->AppendDevicePath (NULL, pDevicePath4); FreePool (pDevicePath4); DevicePathLen3 = DevicePathUtilities->GetDevicePathSize (pDevicePath1); FreePool (pDevicePath1); if (DevicePathLen2 == DevicePathLen3) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gDevicePathUtilitiesBBTestFunctionAssertionGuid059, L"EFI_DEVICE_PATH_UTILITIES_PROTOCOL - AppendDevicePath should ignore Src1 when it is set NULL", L"%a:%d:Status - %r", __FILE__, (UINTN)__LINE__ ); // // TDS 3.4.3.2.2 // pDevicePath1 = (EFI_DEVICE_PATH *) AllocatePool (END_DEVICE_PATH_LENGTH); if (pDevicePath1 == NULL) { return EFI_OUT_OF_RESOURCES; } SetDevicePathEndNode (pDevicePath1); DevicePathLen1 = DevicePathUtilities->GetDevicePathSize (pDevicePath1); pDevicePath2 = DevicePathUtilities->CreateDeviceNode (PCIRootNodeType, PCIRootNodeSubType, PCIRootNodeLength); pDevicePath3 = DevicePathUtilities->AppendDeviceNode (pDevicePath1, pDevicePath2); FreePool (pDevicePath1); FreePool (pDevicePath2); pDevicePath1 = DevicePathUtilities->CreateDeviceNode (PCINodeType, PCINodeSubType, PCINodeLength); pDevicePath2 = DevicePathUtilities->AppendDeviceNode (pDevicePath3, pDevicePath1); FreePool (pDevicePath3); FreePool (pDevicePath1); DevicePathLen1 = DevicePathUtilities->GetDevicePathSize (pDevicePath2); pDevicePath1 = DevicePathUtilities->AppendDevicePath (pDevicePath2, NULL); FreePool (pDevicePath2); DevicePathLen3 = DevicePathUtilities->GetDevicePathSize (pDevicePath1); FreePool (pDevicePath1); if (DevicePathLen1 == DevicePathLen3) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gDevicePathUtilitiesBBTestFunctionAssertionGuid060, L"EFI_DEVICE_PATH_UTILITIES_PROTOCOL - AppendDevicePath should ignore Src2 when it is set NULL", L"%a:%d:Status - %r", __FILE__, (UINTN)__LINE__ ); pDevicePath1 = DevicePathUtilities->AppendDevicePath (NULL, NULL); if ((pDevicePath1 != NULL) && (IsDevicePathEnd(pDevicePath1))) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gDevicePathUtilitiesBBTestFunctionAssertionGuid068, L"EFI_DEVICE_PATH_UTILITIES_PROTOCOL - AppendDevicePath should return end-of-device-path if both Src1 and Src2 are NULL", L"%a:%d", __FILE__, (UINTN)__LINE__ ); return EFI_SUCCESS; }
// // TDS 3.4.4 // EFI_STATUS DevicePathUtilitiesAppendDevicePathInstanceConformanceTest ( IN EFI_BB_TEST_PROTOCOL *This, IN VOID *ClientInterface, IN EFI_TEST_LEVEL TestLevel, IN EFI_HANDLE SupportHandle ) { EFI_STANDARD_TEST_LIBRARY_PROTOCOL *StandardLib; EFI_STATUS Status; EFI_DEVICE_PATH_UTILITIES_PROTOCOL *DevicePathUtilities; EFI_TEST_ASSERTION AssertionType; EFI_DEVICE_PATH_PROTOCOL *pDevicePath1; EFI_DEVICE_PATH_PROTOCOL *pDevicePath2; EFI_DEVICE_PATH_PROTOCOL *pDevicePath3; // // Get the Standard Library Interface // Status = gtBS->HandleProtocol ( SupportHandle, &gEfiStandardTestLibraryGuid, &StandardLib ); if (EFI_ERROR (Status)) { return Status; } DevicePathUtilities = (EFI_DEVICE_PATH_UTILITIES_PROTOCOL *) ClientInterface; // // TDS 3.4.4.2.1 // pDevicePath1 = (EFI_DEVICE_PATH *) AllocatePool (END_DEVICE_PATH_LENGTH); if (pDevicePath1 == NULL) { return EFI_OUT_OF_RESOURCES; } SetDevicePathEndNode (pDevicePath1); pDevicePath2 = DevicePathUtilities->CreateDeviceNode (PCIRootNodeType, PCIRootNodeSubType, PCIRootNodeLength); pDevicePath3 = DevicePathUtilities->AppendDeviceNode (pDevicePath1, pDevicePath2); FreePool (pDevicePath1); FreePool (pDevicePath2); pDevicePath1 = DevicePathUtilities->CreateDeviceNode (PCINodeType, PCINodeSubType, PCINodeLength); pDevicePath2 = DevicePathUtilities->AppendDeviceNode (pDevicePath3, pDevicePath1); FreePool (pDevicePath3); FreePool (pDevicePath1); pDevicePath1 = DevicePathUtilities->AppendDevicePathInstance (pDevicePath2, NULL); FreePool (pDevicePath2); if (pDevicePath1 == NULL) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gDevicePathUtilitiesBBTestFunctionAssertionGuid062, L"EFI_DEVICE_PATH_UTILITIES_PROTOCOL - AppendDevicePathInstance should not succeed with DevicePathInstance set to be NULL", L"%a:%d:Status - %r", __FILE__, (UINTN)__LINE__ ); return EFI_SUCCESS; }
/** Digests the Payload and store the result into the OutData. This function calls relevant Hash interface from CryptoLib according to the input alogrithm ID. It computes all datas from InDataFragment and output the result into the OutData buffer. If the OutDataSize is larger than the related Hash alogrithm output size, return EFI_INVALID_PARAMETER. @param[in] AlgorithmId The authentication Identification. @param[in] InDataFragment A list contains all data to be authenticated. @param[in] FragmentCount The size of the InDataFragment. @param[out] OutData For in, the buffer to receive the output data. For out, the buffer contains the authenticated data. @param[in] OutDataSize The size of the buffer of OutData. @retval EFI_UNSUPPORTED If the AuthAlg is not in the support list. @retval EFI_SUCCESS Authenticated the payload successfully. @retval EFI_INVALID_PARAMETER If the OutDataSize is larger than the related Hash algorithm could handle. @retval otherwise Authentication of the payload failed. **/ EFI_STATUS IpSecCryptoIoHash ( IN CONST UINT8 AlgorithmId, IN HASH_DATA_FRAGMENT *InDataFragment, IN UINTN FragmentCount, OUT UINT8 *OutData, IN UINTN OutDataSize ) { UINTN ContextSize; UINTN Index; UINT8 FragmentIndex; UINT8 *HashContext; EFI_STATUS Status; UINT8 *OutHashData; UINTN OutHashSize; Status = EFI_UNSUPPORTED; OutHashData = NULL; OutHashSize = IpSecGetHmacDigestLength (AlgorithmId); // // If the expected hash data size is larger than the related Hash algorithm // output length, return EFI_INVALID_PARAMETER. // if (OutDataSize > OutHashSize) { return EFI_INVALID_PARAMETER; } OutHashData = AllocatePool (OutHashSize); if (OutHashData == NULL) { return EFI_OUT_OF_RESOURCES; } switch (AlgorithmId) { case IKE_AALG_NONE: case IKE_AALG_NULL: return EFI_SUCCESS; case IKE_AALG_SHA1HMAC: Index = IpSecGetIndexFromAuthList (AlgorithmId); if (Index == -1) { return Status; } // // Get Context Size // ContextSize = mIpsecHashAlgorithmList[Index].HashGetContextSize(); HashContext = AllocateZeroPool (ContextSize); if (HashContext == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Exit; } // // Initiate Hash context and hash the input data. // if (mIpsecHashAlgorithmList[Index].HashInitiate(HashContext)) { for (FragmentIndex = 0; FragmentIndex < FragmentCount; FragmentIndex++) { if (!mIpsecHashAlgorithmList[Index].HashUpdate ( HashContext, InDataFragment[FragmentIndex].Data, InDataFragment[FragmentIndex].DataSize ) ) { goto Exit; } } if (mIpsecHashAlgorithmList[Index].HashFinal (HashContext, OutHashData)) { // // In some cases, like the Icv computing, the Icv size might be less than // the key length size, so copy the part of hash data to the OutData. // CopyMem (OutData, OutHashData, OutDataSize); Status = EFI_SUCCESS; } goto Exit; } default: return Status; } Exit: if (HashContext != NULL) { FreePool (HashContext); } if (OutHashData != NULL) { FreePool (OutHashData); } return Status; }
// // TDS 3.4.2 // EFI_STATUS DevicePathUtilitiesAppendDeviceNodeConformanceTest ( IN EFI_BB_TEST_PROTOCOL *This, IN VOID *ClientInterface, IN EFI_TEST_LEVEL TestLevel, IN EFI_HANDLE SupportHandle ) { EFI_STANDARD_TEST_LIBRARY_PROTOCOL *StandardLib; EFI_STATUS Status; EFI_DEVICE_PATH_UTILITIES_PROTOCOL *DevicePathUtilities; EFI_TEST_ASSERTION AssertionType; EFI_DEVICE_PATH_PROTOCOL *pDevicePath1; EFI_DEVICE_PATH_PROTOCOL *pDevicePath2; EFI_DEVICE_PATH_PROTOCOL *pDevicePath3; EFI_DEVICE_PATH_PROTOCOL *pDevicePath4; // // Get the Standard Library Interface // Status = gtBS->HandleProtocol ( SupportHandle, &gEfiStandardTestLibraryGuid, &StandardLib ); if (EFI_ERROR (Status)) { return Status; } DevicePathUtilities = (EFI_DEVICE_PATH_UTILITIES_PROTOCOL *) ClientInterface; // // TDS 3.4.2.2.1 // pDevicePath1 = (EFI_DEVICE_PATH *) AllocatePool (END_DEVICE_PATH_LENGTH); if (pDevicePath1 == NULL) { return EFI_OUT_OF_RESOURCES; } SetDevicePathEndNode (pDevicePath1); pDevicePath2 = DevicePathUtilities->CreateDeviceNode (PCIRootNodeType, PCIRootNodeSubType, PCIRootNodeLength); pDevicePath4 = DevicePathUtilities->AppendDeviceNode (pDevicePath1, pDevicePath2); pDevicePath3 = DevicePathUtilities->AppendDeviceNode (NULL, pDevicePath2); if ((pDevicePath3 != NULL) && (EfiCompareMem(pDevicePath3, pDevicePath4, DevicePathUtilities->GetDevicePathSize (pDevicePath3)) == 0)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } if (pDevicePath3 != NULL) { FreePool (pDevicePath3); } StandardLib->RecordAssertion ( StandardLib, AssertionType, gDevicePathUtilitiesBBTestFunctionAssertionGuid054, L"EFI_DEVICE_PATH_UTILITIES_PROTOCOL - AppendDeviceNode should return a copy of DeviceNode if DevicePath is NULL", L"%a:%d", __FILE__, (UINTN)__LINE__ ); // // TDS 3.4.2.2.2 // pDevicePath3 = DevicePathUtilities->AppendDeviceNode (pDevicePath4, NULL); if ((pDevicePath3 != NULL) && (EfiCompareMem(pDevicePath3, pDevicePath4, DevicePathUtilities->GetDevicePathSize (pDevicePath3)) == 0)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } if (pDevicePath2 != NULL) { FreePool(pDevicePath2); } if (pDevicePath3 != NULL) { FreePool(pDevicePath3); } if (pDevicePath4 != NULL) { FreePool(pDevicePath4); } StandardLib->RecordAssertion ( StandardLib, AssertionType, gDevicePathUtilitiesBBTestFunctionAssertionGuid055, L"EFI_DEVICE_PATH_UTILITIES_PROTOCOL - AppendDeviceNode should return a copy of DevicePath if DeviceNode is NULL", L"%a:%d", __FILE__, (UINTN)__LINE__ ); pDevicePath3 = DevicePathUtilities->AppendDeviceNode (NULL, NULL); if ((pDevicePath3 != NULL) && (EfiCompareMem(pDevicePath3, pDevicePath1, DevicePathUtilities->GetDevicePathSize (pDevicePath3)) == 0)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } FreePool(pDevicePath1); if (pDevicePath3 != NULL) { FreePool(pDevicePath3); } StandardLib->RecordAssertion ( StandardLib, AssertionType, gDevicePathUtilitiesBBTestFunctionAssertionGuid069, L"EFI_DEVICE_PATH_UTILITIES_PROTOCOL - AppendDeviceNode should return end-of-device-path device node if both DevicePath and DeviceNode are NULL", L"%a:%d", __FILE__, (UINTN)__LINE__ ); return EFI_SUCCESS; }
/** Append a capsule header on top of current image. This function follows Windows UEFI Firmware Update Platform document. @retval EFI_SUCCESS The capsule header is appended. @retval EFI_UNSUPPORTED Input parameter is not valid. @retval EFI_OUT_OF_RESOURCES No enough resource to append capsule header. **/ EFI_STATUS CreateNestedFmp ( VOID ) { CHAR16 *OutputCapsuleName; VOID *CapsuleBuffer; UINTN FileSize; CHAR16 *CapsuleName; UINT8 *FullCapsuleBuffer; UINTN FullCapsuleBufferSize; EFI_CAPSULE_HEADER *NestedCapsuleHeader; EFI_GUID *ImageTypeId; UINT32 FwType; EFI_STATUS Status; if (Argc != 5) { Print(L"CapsuleApp: Incorrect parameter count.\n"); return EFI_UNSUPPORTED; } if (StrCmp(Argv[3], L"-O") != 0) { Print(L"CapsuleApp: NO output capsule name.\n"); return EFI_UNSUPPORTED; } OutputCapsuleName = Argv[4]; CapsuleBuffer = NULL; FileSize = 0; FullCapsuleBuffer = NULL; CapsuleName = Argv[2]; Status = ReadFileToBuffer(CapsuleName, &FileSize, &CapsuleBuffer); if (EFI_ERROR(Status)) { Print(L"CapsuleApp: Capsule image (%s) is not found.\n", CapsuleName); goto Done; } ImageTypeId = GetCapsuleImageTypeId(CapsuleBuffer); if (ImageTypeId == NULL) { Print(L"CapsuleApp: Capsule ImageTypeId is not found.\n"); goto Done; } FwType = GetEsrtFwType(ImageTypeId); if ((FwType != ESRT_FW_TYPE_SYSTEMFIRMWARE) && (FwType != ESRT_FW_TYPE_DEVICEFIRMWARE)) { Print(L"CapsuleApp: Capsule FwType is invalid.\n"); goto Done; } FullCapsuleBufferSize = NESTED_CAPSULE_HEADER_SIZE + FileSize; FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize); if (FullCapsuleBuffer == NULL) { Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n", FullCapsuleBufferSize); Status = EFI_OUT_OF_RESOURCES; goto Done; } NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)FullCapsuleBuffer; ZeroMem(NestedCapsuleHeader, NESTED_CAPSULE_HEADER_SIZE); CopyGuid(&NestedCapsuleHeader->CapsuleGuid, ImageTypeId); NestedCapsuleHeader->HeaderSize = NESTED_CAPSULE_HEADER_SIZE; NestedCapsuleHeader->Flags = (FwType == ESRT_FW_TYPE_SYSTEMFIRMWARE) ? SYSTEM_FIRMWARE_FLAG : DEVICE_FIRMWARE_FLAG; NestedCapsuleHeader->CapsuleImageSize = (UINT32)FullCapsuleBufferSize; CopyMem((UINT8 *)NestedCapsuleHeader + NestedCapsuleHeader->HeaderSize, CapsuleBuffer, FileSize); Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize, FullCapsuleBuffer); Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status); Done: if (CapsuleBuffer != NULL) { FreePool(CapsuleBuffer); } if (FullCapsuleBuffer != NULL) { FreePool(FullCapsuleBuffer); } return Status; }
/** Create UX capsule. @retval EFI_SUCCESS The capsule header is appended. @retval EFI_UNSUPPORTED Input parameter is not valid. @retval EFI_OUT_OF_RESOURCES No enough resource to create UX capsule. **/ EFI_STATUS CreateBmpFmp ( VOID ) { CHAR16 *OutputCapsuleName; VOID *BmpBuffer; UINTN FileSize; CHAR16 *BmpName; UINT8 *FullCapsuleBuffer; UINTN FullCapsuleBufferSize; EFI_DISPLAY_CAPSULE *DisplayCapsule; EFI_STATUS Status; EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBlt; UINTN GopBltSize; UINTN Height; UINTN Width; Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop); if (EFI_ERROR(Status)) { Print(L"CapsuleApp: NO GOP is found.\n"); return EFI_UNSUPPORTED; } Info = Gop->Mode->Info; Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode); Print(L"HorizontalResolution - %d, ", Info->HorizontalResolution); Print(L"VerticalResolution - %d\n", Info->VerticalResolution); // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth // VerticalResolution >= BMP_IMAGE_HEADER.PixelHeight if (Argc != 5) { Print(L"CapsuleApp: Incorrect parameter count.\n"); return EFI_UNSUPPORTED; } if (StrCmp(Argv[3], L"-O") != 0) { Print(L"CapsuleApp: NO output capsule name.\n"); return EFI_UNSUPPORTED; } OutputCapsuleName = Argv[4]; BmpBuffer = NULL; FileSize = 0; FullCapsuleBuffer = NULL; BmpName = Argv[2]; Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer); if (EFI_ERROR(Status)) { Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName); goto Done; } GopBlt = NULL; Status = TranslateBmpToGopBlt ( BmpBuffer, FileSize, &GopBlt, &GopBltSize, &Height, &Width ); if (EFI_ERROR(Status)) { Print(L"CapsuleApp: BMP image (%s) is not valid.\n", BmpName); goto Done; } if (GopBlt != NULL) { FreePool (GopBlt); } Print(L"BMP image (%s), Width - %d, Height - %d\n", BmpName, Width, Height); if (Height > Info->VerticalResolution) { Status = EFI_INVALID_PARAMETER; Print(L"CapsuleApp: BMP image (%s) height is larger than current resolution.\n", BmpName); goto Done; } if (Width > Info->HorizontalResolution) { Status = EFI_INVALID_PARAMETER; Print(L"CapsuleApp: BMP image (%s) width is larger than current resolution.\n", BmpName); goto Done; } FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize; FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize); if (FullCapsuleBuffer == NULL) { Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n", FullCapsuleBufferSize); Status = EFI_OUT_OF_RESOURCES; goto Done; } DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer; CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid); DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader); DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize; DisplayCapsule->ImagePayload.Version = 1; DisplayCapsule->ImagePayload.Checksum = 0; DisplayCapsule->ImagePayload.ImageType = 0; // BMP DisplayCapsule->ImagePayload.Reserved = 0; DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode; // // Center the bitmap horizontally // DisplayCapsule->ImagePayload.OffsetX = (UINT32)((Info->HorizontalResolution - Width) / 2); // // Put bitmap 3/4 down the display. If bitmap is too tall, then align bottom // of bitmap at bottom of display. // DisplayCapsule->ImagePayload.OffsetY = MIN ( (UINT32)(Info->VerticalResolution - Height), (UINT32)(((3 * Info->VerticalResolution) - (2 * Height)) / 4) ); Print(L"BMP image (%s), OffsetX - %d, OffsetY - %d\n", BmpName, DisplayCapsule->ImagePayload.OffsetX, DisplayCapsule->ImagePayload.OffsetY ); CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize); DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer, FullCapsuleBufferSize); Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize, FullCapsuleBuffer); Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status); Done: if (BmpBuffer != NULL) { FreePool(BmpBuffer); } if (FullCapsuleBuffer != NULL) { FreePool(FullCapsuleBuffer); } return Status; }
/** Create the Boot####, Driver####, SysPrep####, PlatformRecovery#### variable from the load option. @param LoadOption Pointer to the load option. @retval EFI_SUCCESS The variable was created. @retval Others Error status returned by RT->SetVariable. **/ EFI_STATUS EFIAPI EfiBootManagerLoadOptionToVariable ( IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Option ) { EFI_STATUS Status; UINTN VariableSize; UINT8 *Variable; UINT8 *Ptr; CHAR16 OptionName[BM_OPTION_NAME_LEN]; CHAR16 *Description; CHAR16 NullChar; EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; UINT32 VariableAttributes; if ((Option->OptionNumber == LoadOptionNumberUnassigned) || (Option->FilePath == NULL) || ((UINT32) Option->OptionType >= LoadOptionTypeMax) ) { return EFI_INVALID_PARAMETER; } // // Convert NULL description to empty description // NullChar = L'\0'; Description = Option->Description; if (Description == NULL) { Description = &NullChar; } /* UINT32 Attributes; UINT16 FilePathListLength; CHAR16 Description[]; EFI_DEVICE_PATH_PROTOCOL FilePathList[]; UINT8 OptionalData[]; TODO: FilePathList[] IS: A packed array of UEFI device paths. The first element of the array is a device path that describes the device and location of the Image for this load option. The FilePathList[0] is specific to the device type. Other device paths may optionally exist in the FilePathList, but their usage is OSV specific. Each element in the array is variable length, and ends at the device path end structure. */ VariableSize = sizeof (Option->Attributes) + sizeof (UINT16) + StrSize (Description) + GetDevicePathSize (Option->FilePath) + Option->OptionalDataSize; Variable = AllocatePool (VariableSize); ASSERT (Variable != NULL); Ptr = Variable; WriteUnaligned32 ((UINT32 *) Ptr, Option->Attributes); Ptr += sizeof (Option->Attributes); WriteUnaligned16 ((UINT16 *) Ptr, (UINT16) GetDevicePathSize (Option->FilePath)); Ptr += sizeof (UINT16); CopyMem (Ptr, Description, StrSize (Description)); Ptr += StrSize (Description); CopyMem (Ptr, Option->FilePath, GetDevicePathSize (Option->FilePath)); Ptr += GetDevicePathSize (Option->FilePath); CopyMem (Ptr, Option->OptionalData, Option->OptionalDataSize); UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", mBmLoadOptionName[Option->OptionType], Option->OptionNumber); VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE; if (Option->OptionType == LoadOptionTypePlatformRecovery) { // // Lock the PlatformRecovery#### // Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock); if (!EFI_ERROR (Status)) { Status = VariableLock->RequestToLock (VariableLock, OptionName, &gEfiGlobalVariableGuid); ASSERT_EFI_ERROR (Status); } VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; } Status = gRT->SetVariable ( OptionName, &gEfiGlobalVariableGuid, VariableAttributes, VariableSize, Variable ); FreePool (Variable); return Status; }
/** Restore Partition Table to its alternate place (Primary -> Backup or Backup -> Primary). @param[in] BlockIo Parent BlockIo interface. @param[in] DiskIo Disk Io Protocol. @param[in] PartHeader Partition table header structure. @retval TRUE Restoring succeeds @retval FALSE Restoring failed **/ BOOLEAN PartitionRestoreGptTable ( IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_PARTITION_TABLE_HEADER *PartHeader ) { EFI_STATUS Status; UINTN BlockSize; EFI_PARTITION_TABLE_HEADER *PartHdr; EFI_LBA PEntryLBA; UINT8 *Ptr; UINT32 MediaId; PartHdr = NULL; Ptr = NULL; BlockSize = BlockIo->Media->BlockSize; MediaId = BlockIo->Media->MediaId; PartHdr = AllocateZeroPool (BlockSize); if (PartHdr == NULL) { DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); return FALSE; } PEntryLBA = (PartHeader->MyLBA == PRIMARY_PART_HEADER_LBA) ? \ (PartHeader->LastUsableLBA + 1) : \ (PRIMARY_PART_HEADER_LBA + 1); CopyMem (PartHdr, PartHeader, sizeof (EFI_PARTITION_TABLE_HEADER)); PartHdr->MyLBA = PartHeader->AlternateLBA; PartHdr->AlternateLBA = PartHeader->MyLBA; PartHdr->PartitionEntryLBA = PEntryLBA; PartitionSetCrc ((EFI_TABLE_HEADER *) PartHdr); Status = DiskIo->WriteDisk ( DiskIo, MediaId, MultU64x32 (PartHdr->MyLBA, (UINT32) BlockSize), BlockSize, PartHdr ); if (EFI_ERROR (Status)) { goto Done; } Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry); if (Ptr == NULL) { DEBUG ((EFI_D_ERROR, " Allocate pool error\n")); Status = EFI_OUT_OF_RESOURCES; goto Done; } Status = DiskIo->ReadDisk ( DiskIo, MediaId, MultU64x32(PartHeader->PartitionEntryLBA, (UINT32) BlockSize), PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry, Ptr ); if (EFI_ERROR (Status)) { goto Done; } Status = DiskIo->WriteDisk ( DiskIo, MediaId, MultU64x32(PEntryLBA, (UINT32) BlockSize), PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry, Ptr ); Done: FreePool (PartHdr); if (Ptr != NULL) { FreePool (Ptr); } if (EFI_ERROR (Status)) { return FALSE; } return TRUE; }
EFI_STATUS EFIAPI QemuVideoGraphicsOutputSetMode ( IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, IN UINT32 ModeNumber ) /*++ Routine Description: Graphics Output protocol interface to set video mode Arguments: This - Protocol instance pointer. ModeNumber - The mode number to be set. Returns: EFI_SUCCESS - Graphics mode was changed. EFI_DEVICE_ERROR - The device had an error and could not complete the request. EFI_UNSUPPORTED - ModeNumber is not supported by this device. --*/ { QEMU_VIDEO_PRIVATE_DATA *Private; QEMU_VIDEO_MODE_DATA *ModeData; // UINTN Count; Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This); if (ModeNumber >= This->Mode->MaxMode) { return EFI_UNSUPPORTED; } ModeData = &Private->ModeData[ModeNumber]; if (Private->LineBuffer) { gBS->FreePool (Private->LineBuffer); } Private->LineBuffer = AllocatePool (4 * ModeData->HorizontalResolution); if (Private->LineBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } switch (Private->Variant) { case QEMU_VIDEO_CIRRUS_5430: case QEMU_VIDEO_CIRRUS_5446: InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]); break; case QEMU_VIDEO_BOCHS_MMIO: case QEMU_VIDEO_BOCHS: InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]); break; default: ASSERT (FALSE); gBS->FreePool (Private->LineBuffer); Private->LineBuffer = NULL; return EFI_DEVICE_ERROR; } This->Mode->Mode = ModeNumber; This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution; This->Mode->Info->VerticalResolution = ModeData->VerticalResolution; This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); QemuVideoCompleteModeData (Private, This->Mode); BltLibConfigure ( (VOID*)(UINTN) This->Mode->FrameBufferBase, This->Mode->Info ); return EFI_SUCCESS; }
/** Retrieve the host address using the EFI_DNS6_PROTOCOL. @param[in] Private The pointer to the driver's private data. @param[in] HostName Pointer to buffer containing hostname. @param[out] IpAddress On output, pointer to buffer containing IPv6 address. @retval EFI_SUCCESS Operation succeeded. @retval EFI_DEVICE_ERROR An unexpected network error occurred. @retval Others Other errors as indicated. **/ EFI_STATUS HttpBootDns ( IN HTTP_BOOT_PRIVATE_DATA *Private, IN CHAR16 *HostName, OUT EFI_IPv6_ADDRESS *IpAddress ) { EFI_STATUS Status; EFI_DNS6_PROTOCOL *Dns6; EFI_DNS6_CONFIG_DATA Dns6ConfigData; EFI_DNS6_COMPLETION_TOKEN Token; EFI_HANDLE Dns6Handle; EFI_IP6_CONFIG_PROTOCOL *Ip6Config; EFI_IPv6_ADDRESS *DnsServerList; UINTN DnsServerListCount; UINTN DataSize; BOOLEAN IsDone; DnsServerList = NULL; DnsServerListCount = 0; Dns6 = NULL; Dns6Handle = NULL; ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN)); // // Get DNS server list from EFI IPv6 Configuration protocol. // Status = gBS->HandleProtocol (Private->Controller, &gEfiIp6ConfigProtocolGuid, (VOID **) &Ip6Config); if (!EFI_ERROR (Status)) { // // Get the required size. // DataSize = 0; Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL); if (Status == EFI_BUFFER_TOO_SMALL) { DnsServerList = AllocatePool (DataSize); if (DnsServerList == NULL) { return EFI_OUT_OF_RESOURCES; } Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList); if (EFI_ERROR (Status)) { FreePool (DnsServerList); DnsServerList = NULL; } else { DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS); } } } // // Create a DNSv6 child instance and get the protocol. // Status = NetLibCreateServiceChild ( Private->Controller, Private->Ip6Nic->ImageHandle, &gEfiDns6ServiceBindingProtocolGuid, &Dns6Handle ); if (EFI_ERROR (Status)) { goto Exit; } Status = gBS->OpenProtocol ( Dns6Handle, &gEfiDns6ProtocolGuid, (VOID **) &Dns6, Private->Ip6Nic->ImageHandle, Private->Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto Exit; } // // Configure DNS6 instance for the DNS server address and protocol. // ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA)); Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount; Dns6ConfigData.DnsServerList = DnsServerList; Dns6ConfigData.EnableDnsCache = TRUE; Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP; IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp,&Private->StationIp.v6); Status = Dns6->Configure ( Dns6, &Dns6ConfigData ); if (EFI_ERROR (Status)) { goto Exit; } Token.Status = EFI_NOT_READY; IsDone = FALSE; // // Create event to set the IsDone flag when name resolution is finished. // Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, HttpBootCommonNotify, &IsDone, &Token.Event ); if (EFI_ERROR (Status)) { goto Exit; } // // Start asynchronous name resolution. // Status = Dns6->HostNameToIp (Dns6, HostName, &Token); if (EFI_ERROR (Status)) { goto Exit; } while (!IsDone) { Dns6->Poll (Dns6); } // // Name resolution is done, check result. // Status = Token.Status; if (!EFI_ERROR (Status)) { if (Token.RspData.H2AData == NULL) { Status = EFI_DEVICE_ERROR; goto Exit; } if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) { Status = EFI_DEVICE_ERROR; goto Exit; } // // We just return the first IPv6 address from DNS protocol. // IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList); Status = EFI_SUCCESS; } Exit: if (Token.Event != NULL) { gBS->CloseEvent (Token.Event); } if (Token.RspData.H2AData != NULL) { if (Token.RspData.H2AData->IpList != NULL) { FreePool (Token.RspData.H2AData->IpList); } FreePool (Token.RspData.H2AData); } if (Dns6 != NULL) { Dns6->Configure (Dns6, NULL); gBS->CloseProtocol ( Dns6Handle, &gEfiDns6ProtocolGuid, Private->Ip6Nic->ImageHandle, Private->Controller ); } if (Dns6Handle != NULL) { NetLibDestroyServiceChild ( Private->Controller, Private->Ip6Nic->ImageHandle, &gEfiDns6ServiceBindingProtocolGuid, Dns6Handle ); } if (DnsServerList != NULL) { FreePool (DnsServerList); } return Status; }
EFI_STATUS UtilIterateVariables ( IN VARIABLE_ITERATION_CALLBACK CallbackFunction, IN VOID *Context ) { RETURN_STATUS Status; UINTN VariableNameBufferSize; UINTN VariableNameSize; CHAR16 *VariableName; EFI_GUID VendorGuid; UINTN VariableDataBufferSize; UINTN VariableDataSize; VOID *VariableData; UINT32 VariableAttributes; VOID *NewBuffer; // // Initialize the variable name and data buffer variables. // VariableNameBufferSize = sizeof (CHAR16); VariableName = AllocateZeroPool (VariableNameBufferSize); VariableDataBufferSize = 0; VariableData = NULL; for (;;) { // // Get the next variable name and guid // VariableNameSize = VariableNameBufferSize; Status = gRT->GetNextVariableName ( &VariableNameSize, VariableName, &VendorGuid ); if (Status == EFI_BUFFER_TOO_SMALL) { // // The currently allocated VariableName buffer is too small, // so we allocate a larger buffer, and copy the old buffer // to it. // NewBuffer = AllocatePool (VariableNameSize); if (NewBuffer == NULL) { Status = EFI_OUT_OF_RESOURCES; break; } CopyMem (NewBuffer, VariableName, VariableNameBufferSize); if (VariableName != NULL) { FreePool (VariableName); } VariableName = NewBuffer; VariableNameBufferSize = VariableNameSize; // // Try to get the next variable name again with the larger buffer. // Status = gRT->GetNextVariableName ( &VariableNameSize, VariableName, &VendorGuid ); } if (EFI_ERROR (Status)) { if (Status == EFI_NOT_FOUND) { Status = EFI_SUCCESS; } break; } // // Get the variable data and attributes // VariableDataSize = VariableDataBufferSize; Status = gRT->GetVariable ( VariableName, &VendorGuid, &VariableAttributes, &VariableDataSize, VariableData ); if (Status == EFI_BUFFER_TOO_SMALL) { // // The currently allocated VariableData buffer is too small, // so we allocate a larger buffer. // if (VariableDataBufferSize != 0) { FreePool (VariableData); VariableData = NULL; VariableDataBufferSize = 0; } VariableData = AllocatePool (VariableDataSize); if (VariableData == NULL) { Status = EFI_OUT_OF_RESOURCES; break; } VariableDataBufferSize = VariableDataSize; // // Try to read the variable again with the larger buffer. // Status = gRT->GetVariable ( VariableName, &VendorGuid, &VariableAttributes, &VariableDataSize, VariableData ); } if (EFI_ERROR (Status)) { break; } // // Run the callback function // Status = (*CallbackFunction) ( Context, VariableName, &VendorGuid, VariableAttributes, VariableDataSize, VariableData ); if (EFI_ERROR (Status)) { break; } } if (VariableName != NULL) { FreePool (VariableName); } if (VariableData != NULL) { FreePool (VariableData); } return Status; }
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; }
/** Install child handles if the Handle supports El Torito format. @param[in] This Calling context. @param[in] Handle Parent Handle. @param[in] DiskIo Parent DiskIo interface. @param[in] BlockIo Parent BlockIo interface. @param[in] BlockIo2 Parent BlockIo2 interface. @param[in] DevicePath Parent Device Path @retval EFI_SUCCESS Child handle(s) was added. @retval EFI_MEDIA_CHANGED Media changed Detected. @retval other no child handle was added. **/ EFI_STATUS PartitionInstallElToritoChildHandles ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_STATUS Status; UINT32 VolDescriptorLba; UINT32 Lba; EFI_BLOCK_IO_MEDIA *Media; CDROM_VOLUME_DESCRIPTOR *VolDescriptor; ELTORITO_CATALOG *Catalog; UINTN Check; UINTN Index; UINTN BootEntry; UINTN MaxIndex; UINT16 *CheckBuffer; CDROM_DEVICE_PATH CdDev; UINT32 SubBlockSize; UINT32 SectorCount; EFI_STATUS Found; UINT32 VolSpaceSize; #ifdef VBOX VBoxLogFlowFuncMarkDP(DevicePath); #endif Found = EFI_NOT_FOUND; Media = BlockIo->Media; VolSpaceSize = 0; // // CD_ROM has the fixed block size as 2048 bytes // if (Media->BlockSize != 2048) { return EFI_NOT_FOUND; } VolDescriptor = AllocatePool ((UINTN) Media->BlockSize); if (VolDescriptor == NULL) { return EFI_NOT_FOUND; } Catalog = (ELTORITO_CATALOG *) VolDescriptor; // // the ISO-9660 volume descriptor starts at 32k on the media // and CD_ROM has the fixed block size as 2048 bytes, so... // // // ((16*2048) / Media->BlockSize) - 1; // VolDescriptorLba = 15; // // Loop: handle one volume descriptor per time // while (TRUE) { VolDescriptorLba += 1; if (VolDescriptorLba > Media->LastBlock) { // // We are pointing past the end of the device so exit // break; } Status = DiskIo->ReadDisk ( DiskIo, Media->MediaId, MultU64x32 (VolDescriptorLba, Media->BlockSize), Media->BlockSize, VolDescriptor ); if (EFI_ERROR (Status)) { Found = Status; break; } // // Check for valid volume descriptor signature // if (VolDescriptor->Unknown.Type == CDVOL_TYPE_END || CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0 ) { // // end of Volume descriptor list // break; } // // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte, // the 32-bit numerical values is stored in Both-byte orders // if (VolDescriptor->PrimaryVolume.Type == CDVOL_TYPE_CODED) { VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[0]; } // // Is it an El Torito volume descriptor? // if (CompareMem (VolDescriptor->BootRecordVolume.SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1) != 0) { continue; } // // Read in the boot El Torito boot catalog // Lba = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog); if (Lba > Media->LastBlock) { continue; } Status = DiskIo->ReadDisk ( DiskIo, Media->MediaId, MultU64x32 (Lba, Media->BlockSize), Media->BlockSize, Catalog ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "EltCheckDevice: error reading catalog %r\n", Status)); continue; } // // We don't care too much about the Catalog header's contents, but we do want // to make sure it looks like a Catalog header // if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) { DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n")); continue; } Check = 0; CheckBuffer = (UINT16 *) Catalog; for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) { Check += CheckBuffer[Index]; } if ((Check & 0xFFFF) != 0) { DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n")); continue; } MaxIndex = Media->BlockSize / sizeof (ELTORITO_CATALOG); for (Index = 1, BootEntry = 1; Index < MaxIndex; Index += 1) { // // Next entry // Catalog += 1; // // Check this entry // if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) { continue; } SubBlockSize = 512; SectorCount = Catalog->Boot.SectorCount; switch (Catalog->Boot.MediaType) { case ELTORITO_NO_EMULATION: SubBlockSize = Media->BlockSize; break; case ELTORITO_HARD_DISK: break; case ELTORITO_12_DISKETTE: SectorCount = 0x50 * 0x02 * 0x0F; break; case ELTORITO_14_DISKETTE: SectorCount = 0x50 * 0x02 * 0x12; break; case ELTORITO_28_DISKETTE: SectorCount = 0x50 * 0x02 * 0x24; break; default: DEBUG ((EFI_D_INIT, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog->Boot.MediaType)); SectorCount = 0; SubBlockSize = Media->BlockSize; break; } // // Create child device handle // CdDev.Header.Type = MEDIA_DEVICE_PATH; CdDev.Header.SubType = MEDIA_CDROM_DP; SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev)); if (Index == 1) { // // This is the initial/default entry // BootEntry = 0; } CdDev.BootEntry = (UINT32) BootEntry; BootEntry++; CdDev.PartitionStart = Catalog->Boot.Lba; if (SectorCount < 2) { // // When the SectorCount < 2, set the Partition as the whole CD. // if (VolSpaceSize > (Media->LastBlock + 1)) { CdDev.PartitionSize = (UINT32)(Media->LastBlock - Catalog->Boot.Lba + 1); } else { CdDev.PartitionSize = (UINT32)(VolSpaceSize - Catalog->Boot.Lba); } } else { CdDev.PartitionSize = DivU64x32 ( MultU64x32 ( SectorCount, SubBlockSize ) + Media->BlockSize - 1, Media->BlockSize ); } Status = PartitionInstallChildHandle ( This, Handle, DiskIo, BlockIo, BlockIo2, DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &CdDev, Catalog->Boot.Lba, Catalog->Boot.Lba + CdDev.PartitionSize - 1, SubBlockSize, FALSE ); if (!EFI_ERROR (Status)) { Found = EFI_SUCCESS; } } } FreePool (VolDescriptor); return Found; }
void console_print_box_at(CHAR16 *str_arr[], int highlight, int start_col, int start_row, int size_cols, int size_rows, int offset, int lines) { int i; SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; UINTN rows, cols; CHAR16 *Line; if (lines == 0) return; uefi_call_wrapper(co->QueryMode, 4, co, co->Mode->Mode, &cols, &rows); /* last row on screen is unusable without scrolling, so ignore it */ rows--; if (size_rows < 0) size_rows = rows + size_rows + 1; if (size_cols < 0) size_cols = cols + size_cols + 1; if (start_col < 0) start_col = (cols + start_col + 2)/2; if (start_row < 0) start_row = (rows + start_row + 2)/2; if (start_col < 0) start_col = 0; if (start_row < 0) start_row = 0; if (start_col > cols || start_row > rows) { Print(L"Starting Position (%d,%d) is off screen\n", start_col, start_row); return; } if (size_cols + start_col > cols) size_cols = cols - start_col; if (size_rows + start_row > rows) size_rows = rows - start_row; if (lines > size_rows - 2) lines = size_rows - 2; Line = AllocatePool((size_cols+1)*sizeof(CHAR16)); if (!Line) { Print(L"Failed Allocation\n"); return; } SetMem16 (Line, size_cols * 2, BOXDRAW_HORIZONTAL); Line[0] = BOXDRAW_DOWN_RIGHT; Line[size_cols - 1] = BOXDRAW_DOWN_LEFT; Line[size_cols] = L'\0'; uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, start_row); uefi_call_wrapper(co->OutputString, 2, co, Line); int start; if (offset == 0) /* middle */ start = (size_rows - lines)/2 + start_row + offset; else if (offset < 0) /* from bottom */ start = start_row + size_rows - lines + offset - 1; else /* from top */ start = start_row + offset; for (i = start_row + 1; i < size_rows + start_row - 1; i++) { int line = i - start; SetMem16 (Line, size_cols*2, L' '); Line[0] = BOXDRAW_VERTICAL; Line[size_cols - 1] = BOXDRAW_VERTICAL; Line[size_cols] = L'\0'; if (line >= 0 && line < lines) { CHAR16 *s = str_arr[line]; int len = StrLen(s); int col = (size_cols - 2 - len)/2; if (col < 0) col = 0; CopyMem(Line + col + 1, s, min(len, size_cols - 2)*2); } if (line >= 0 && line == highlight) uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK); uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, i); uefi_call_wrapper(co->OutputString, 2, co, Line); if (line >= 0 && line == highlight) uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); } SetMem16 (Line, size_cols * 2, BOXDRAW_HORIZONTAL); Line[0] = BOXDRAW_UP_RIGHT; Line[size_cols - 1] = BOXDRAW_UP_LEFT; Line[size_cols] = L'\0'; uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, i); uefi_call_wrapper(co->OutputString, 2, co, Line); FreePool (Line); }
EFI_STATUS EblGetCmd ( IN UINTN Argc, IN CHAR8 **Argv ) { EFI_STATUS Status = EFI_INVALID_PARAMETER; UINTN Size; VOID* Value; CHAR8* AsciiVariableName = NULL; CHAR16* VariableName; UINT32 Index; if (Argc == 1) { AsciiPrint("Variable name is missing.\n"); return Status; } for (Index = 1; Index < Argc; Index++) { if (Argv[Index][0] == '-') { AsciiPrint("Warning: '%a' not recognized.\n",Argv[Index]); } else { AsciiVariableName = Argv[Index]; } } if (AsciiVariableName == NULL) { AsciiPrint("Variable name is missing.\n"); return Status; } else { VariableName = AllocatePool((AsciiStrLen (AsciiVariableName) + 1) * sizeof (CHAR16)); AsciiStrToUnicodeStr (AsciiVariableName,VariableName); } // Try to get the variable size. Value = NULL; Size = 0; Status = gRT->GetVariable (VariableName, &gEfiGlobalVariableGuid, NULL, &Size, Value); if (Status == EFI_NOT_FOUND) { AsciiPrint("Variable name '%s' not found.\n",VariableName); } else if (Status == EFI_BUFFER_TOO_SMALL) { // Get the environment variable value Value = AllocatePool (Size); if (Value == NULL) { return EFI_OUT_OF_RESOURCES; } Status = gRT->GetVariable ((CHAR16 *)VariableName, &gEfiGlobalVariableGuid, NULL, &Size, Value); if (EFI_ERROR (Status)) { AsciiPrint("Error: '%r'\n",Status); } else { AsciiPrint("%a=%a\n",AsciiVariableName,Value); } FreePool(Value); } else { AsciiPrint("Error: '%r'\n",Status); } FreePool(VariableName); return Status; }
/** Open a file on the host system by means of the semihosting interface. @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file handle to source location. @param[out] NewHandle A pointer to the location to return the opened handle for the new file. @param[in] FileName The Null-terminated string of the name of the file to be opened. @param[in] OpenMode The mode to open the file : Read or Read/Write or Read/Write/Create @param[in] Attributes Only valid for EFI_FILE_MODE_CREATE, in which case these are the attribute bits for the newly created file. The mnemonics of the attribute bits are : EFI_FILE_READ_ONLY, EFI_FILE_HIDDEN, EFI_FILE_SYSTEM, EFI_FILE_RESERVED, EFI_FILE_DIRECTORY and EFI_FILE_ARCHIVE. @retval EFI_SUCCESS The file was open. @retval EFI_NOT_FOUND The specified file could not be found. @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed. @retval EFI_WRITE_PROTECTED Attempt to create a directory. This is not possible with the semi-hosting interface. @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file. @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. **/ EFI_STATUS FileOpen ( IN EFI_FILE *This, OUT EFI_FILE **NewHandle, IN CHAR16 *FileName, IN UINT64 OpenMode, IN UINT64 Attributes ) { SEMIHOST_FCB *FileFcb; RETURN_STATUS Return; EFI_STATUS Status; UINTN SemihostHandle; CHAR8 *AsciiFileName; UINT32 SemihostMode; UINTN Length; if ((FileName == NULL) || (NewHandle == NULL)) { return EFI_INVALID_PARAMETER; } if ( (OpenMode != EFI_FILE_MODE_READ) && (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE)) && (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE)) ) { return EFI_INVALID_PARAMETER; } if ((OpenMode & EFI_FILE_MODE_CREATE) && (Attributes & EFI_FILE_DIRECTORY) ) { return EFI_WRITE_PROTECTED; } AsciiFileName = AllocatePool (StrLen (FileName) + 1); if (AsciiFileName == NULL) { return EFI_OUT_OF_RESOURCES; } UnicodeStrToAsciiStr (FileName, AsciiFileName); // Opening '/', '\', '.', or the NULL pathname is trying to open the root directory if ((AsciiStrCmp (AsciiFileName, "\\") == 0) || (AsciiStrCmp (AsciiFileName, "/") == 0) || (AsciiStrCmp (AsciiFileName, "") == 0) || (AsciiStrCmp (AsciiFileName, ".") == 0) ) { FreePool (AsciiFileName); return (VolumeOpen (&gSemihostFs, NewHandle)); } // // No control is done here concerning the file path. It is passed // as it is to the host operating system through the semi-hosting // interface. We first try to open the file in the read or update // mode even if the file creation has been asked for. That way, if // the file already exists, it is not truncated to zero length. In // write mode (bit SEMIHOST_FILE_MODE_WRITE up), if the file already // exists, it is reset to an empty file. // if (OpenMode == EFI_FILE_MODE_READ) { SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY; } else { SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY | SEMIHOST_FILE_MODE_UPDATE; } Return = SemihostFileOpen (AsciiFileName, SemihostMode, &SemihostHandle); if (RETURN_ERROR (Return)) { if (OpenMode & EFI_FILE_MODE_CREATE) { // // In the create if does not exist case, if the opening in update // mode failed, create it and open it in update mode. The update // mode allows for both read and write from and to the file. // Return = SemihostFileOpen ( AsciiFileName, SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY | SEMIHOST_FILE_MODE_UPDATE, &SemihostHandle ); if (RETURN_ERROR (Return)) { Status = EFI_DEVICE_ERROR; goto Error; } } else { Status = EFI_NOT_FOUND; goto Error; } } // Allocate a control block and fill it FileFcb = AllocateFCB (); if (FileFcb == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error; } FileFcb->FileName = AsciiFileName; FileFcb->SemihostHandle = SemihostHandle; FileFcb->Position = 0; FileFcb->IsRoot = 0; FileFcb->OpenMode = OpenMode; Return = SemihostFileLength (SemihostHandle, &Length); if (RETURN_ERROR (Return)) { Status = EFI_DEVICE_ERROR; FreeFCB (FileFcb); goto Error; } FileFcb->Info.FileSize = Length; FileFcb->Info.PhysicalSize = Length; FileFcb->Info.Attribute = (OpenMode & EFI_FILE_MODE_CREATE) ? Attributes : 0; InsertTailList (&gFileList, &FileFcb->Link); *NewHandle = &FileFcb->File; return EFI_SUCCESS; Error: FreePool (AsciiFileName); return Status; }
EFI_STATUS EblSetCmd ( IN UINTN Argc, IN CHAR8 **Argv ) { EFI_STATUS Status = EFI_INVALID_PARAMETER; CHAR8* AsciiVariableSetting = NULL; CHAR8* AsciiVariableName; CHAR8* AsciiValue; UINT32 AsciiValueLength; CHAR16* VariableName; UINT32 Index; UINT32 EscapedQuotes = 0; BOOLEAN Volatile = FALSE; if (Argc == 1) { AsciiPrint("Variable name is missing.\n"); return Status; } for (Index = 1; Index < Argc; Index++) { if (AsciiStrCmp(Argv[Index],"-v") == 0) { Volatile = 0; } else if (Argv[Index][0] == '-') { AsciiPrint("Warning: '%a' not recognized.\n",Argv[Index]); } else { AsciiVariableSetting = Argv[Index]; } } if (AsciiVariableSetting == NULL) { AsciiPrint("Variable name is missing.\n"); return Status; } // Check if it is a valid variable setting AsciiValue = AsciiStrStr (AsciiVariableSetting,"="); if (AsciiValue == NULL) { // // There is no value. It means this variable will be deleted // // Convert VariableName into Unicode VariableName = AllocatePool((AsciiStrLen (AsciiVariableSetting) + 1) * sizeof (CHAR16)); AsciiStrToUnicodeStr (AsciiVariableSetting,VariableName); Status = gRT->SetVariable ( VariableName, &gEfiGlobalVariableGuid, ( !Volatile ? EFI_VARIABLE_NON_VOLATILE : 0) | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 0, NULL ); if (!EFI_ERROR(Status)) { AsciiPrint("Variable '%s' deleted\n",VariableName); } else { AsciiPrint("Variable setting is incorrect. It should be VariableName=Value\n"); } return Status; } AsciiValue[0] = '\0'; AsciiVariableName = AsciiVariableSetting; AsciiValue++; // Clean AsciiValue from quote if (AsciiValue[0] == '"') { AsciiValue++; } AsciiValueLength = AsciiStrLen (AsciiValue); if ((AsciiValue[AsciiValueLength-2] != '\\') && (AsciiValue[AsciiValueLength-1] == '"')) { AsciiValue[AsciiValueLength-1] = '\0'; } // Clean AsciiValue from escaped quotes for (Index = 0; Index < AsciiValueLength; Index++) { if ((Index > 0) && (AsciiValue[Index-1] == '\\') && (AsciiValue[Index] == '"')) { EscapedQuotes++; } AsciiValue[Index-EscapedQuotes] = AsciiValue[Index]; } // Fill the end of the value with '\0' for (Index = 0; Index < EscapedQuotes; Index++) { AsciiValue[AsciiValueLength-1-Index] = '\0'; } // Convert VariableName into Unicode VariableName = AllocatePool((AsciiStrLen (AsciiVariableName) + 1) * sizeof (CHAR16)); AsciiStrToUnicodeStr (AsciiVariableName,VariableName); Status = gRT->SetVariable ( VariableName, &gEfiGlobalVariableGuid, ( !Volatile ? EFI_VARIABLE_NON_VOLATILE : 0) | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, AsciiStrLen (AsciiValue)+1, AsciiValue ); if (!EFI_ERROR(Status)) { AsciiPrint("'%a'='%a'\n",AsciiVariableName,AsciiValue); } return Status; }
/** Set information about a file. @param[in] Fcb A pointer to the description of the open file. @param[in] Info A pointer to the file information to write. @retval EFI_SUCCESS The information was set. @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file to a file that is already present. @retval EFI_ACCESS_DENIED An attempt is being made to change the EFI_FILE_DIRECTORY Attribute. @retval EFI_ACCESS_DENIED The file is a read-only file or has been opened in read-only mode and an attempt is being made to modify a field other than Attribute. @retval EFI_WRITE_PROTECTED An attempt is being made to modify a read-only attribute. @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed. @retval EFI_OUT_OF_RESOURCES A allocation needed to process the request failed. **/ STATIC EFI_STATUS SetFileInfo ( IN SEMIHOST_FCB *Fcb, IN EFI_FILE_INFO *Info ) { EFI_STATUS Status; RETURN_STATUS Return; BOOLEAN FileSizeIsDifferent; BOOLEAN FileNameIsDifferent; BOOLEAN ReadOnlyIsDifferent; CHAR8 *AsciiFileName; UINTN FileSize; UINTN Length; UINTN SemihostHandle; // // A directory can not be changed to a file and a file can // not be changed to a directory. // if (((Info->Attribute & EFI_FILE_DIRECTORY) != 0) != Fcb->IsRoot) { return EFI_ACCESS_DENIED; } AsciiFileName = AllocatePool (StrLen (Info->FileName) + 1); if (AsciiFileName == NULL) { return EFI_OUT_OF_RESOURCES; } UnicodeStrToAsciiStr (Info->FileName, AsciiFileName); FileSizeIsDifferent = (Info->FileSize != Fcb->Info.FileSize); FileNameIsDifferent = (AsciiStrCmp (AsciiFileName, Fcb->FileName) != 0); ReadOnlyIsDifferent = CompareMem ( &Info->CreateTime, &Fcb->Info.CreateTime, 3 * sizeof (EFI_TIME) ) != 0; // // For a read-only file or a file opened in read-only mode, only // the Attribute field can be modified. As the root directory is // read-only (i.e. VolumeOpen()), this protects the root directory // description. // if ((Fcb->OpenMode == EFI_FILE_MODE_READ) || (Fcb->Info.Attribute & EFI_FILE_READ_ONLY) ) { if (FileSizeIsDifferent || FileNameIsDifferent || ReadOnlyIsDifferent) { Status = EFI_ACCESS_DENIED; goto Error; } } if (ReadOnlyIsDifferent) { Status = EFI_WRITE_PROTECTED; goto Error; } Status = EFI_DEVICE_ERROR; if (FileSizeIsDifferent) { FileSize = Info->FileSize; if (Fcb->Info.FileSize < FileSize) { Status = ExtendFile (Fcb, FileSize - Fcb->Info.FileSize); if (EFI_ERROR (Status)) { goto Error; } // // The read/write position from the host file system point of view // is at the end of the file. If the position from this module // point of view is smaller than the new file size, then // ask the host file system to move to that position. // if (Fcb->Position < FileSize) { FileSetPosition (&Fcb->File, Fcb->Position); } } Fcb->Info.FileSize = FileSize; Return = SemihostFileLength (Fcb->SemihostHandle, &Length); if (RETURN_ERROR (Return)) { goto Error; } Fcb->Info.PhysicalSize = Length; } // // Note down in RAM the Attribute field but we can not ask // for its modification to the host file system as the // semi-host interface does not provide this feature. // Fcb->Info.Attribute = Info->Attribute; if (FileNameIsDifferent) { Return = SemihostFileOpen ( AsciiFileName, SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY, &SemihostHandle ); if (!RETURN_ERROR (Return)) { SemihostFileClose (SemihostHandle); Status = EFI_ACCESS_DENIED; goto Error; } Return = SemihostFileRename (Fcb->FileName, AsciiFileName); if (RETURN_ERROR (Return)) { goto Error; } FreePool (Fcb->FileName); Fcb->FileName = AsciiFileName; AsciiFileName = NULL; } Status = EFI_SUCCESS; Error: if (AsciiFileName != NULL) { FreePool (AsciiFileName); } return Status; }
/** Install child handles if the Handle supports Apple partition table format. @param[in] This Calling context. @param[in] Handle Parent Handle @param[in] DiskIo Parent DiskIo interface @param[in] BlockIo Parent BlockIo interface @param[in] DevicePath Parent Device Path @retval EFI_SUCCESS Child handle(s) was added @retval EFI_MEDIA_CHANGED Media changed Detected @retval other no child handle was added **/ EFI_STATUS PartitionInstallAppleChildHandles ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_STATUS Status; UINT32 Lba; EFI_BLOCK_IO_MEDIA *Media; VOID *Block; //UINTN MaxIndex; /** @todo: wrong, as this PT can be on both HDD or CD */ CDROM_DEVICE_PATH CdDev; //EFI_DEVICE_PATH_PROTOCOL Dev; EFI_STATUS Found; UINT32 Partition; UINT32 PartitionEntries; UINT32 VolSpaceSize; UINT32 SubBlockSize; UINT32 BlkPerSec; VBoxLogFlowFuncMarkDP(DevicePath); Found = EFI_NOT_FOUND; Media = BlockIo->Media; VolSpaceSize = 0; Block = AllocatePool ((UINTN) Media->BlockSize); if (Block == NULL) { return EFI_NOT_FOUND; } do { APPLE_PT_HEADER * Header; /* read PT header first */ Lba = 0; Status = DiskIo->ReadDisk ( DiskIo, Media->MediaId, MultU64x32 (Lba, Media->BlockSize), Media->BlockSize, Block ); if (EFI_ERROR (Status)) { Found = Status; break; } Header = (APPLE_PT_HEADER *)Block; if (be16_to_cpu(Header->sbSig) != 0x4552) { break; } SubBlockSize = be16_to_cpu(Header->sbBlkSize); BlkPerSec = Media->BlockSize / SubBlockSize; /* Fail if media block size isn't an exact multiple */ if (Media->BlockSize != SubBlockSize * BlkPerSec) { break; } /* Now iterate over PT entries and install child handles */ PartitionEntries = 1; for (Partition = 1; Partition <= PartitionEntries; Partition++) { APPLE_PT_ENTRY * Entry; UINT32 StartLba; UINT32 SizeLbs; Status = DiskIo->ReadDisk ( DiskIo, Media->MediaId, MultU64x32 (Partition, SubBlockSize), SubBlockSize, Block ); if (EFI_ERROR (Status)) { Status = EFI_NOT_FOUND; goto done; /* would break, but ... */ } Entry = (APPLE_PT_ENTRY *)Block; if (be16_to_cpu(Entry->signature) != 0x504D) { Print(L"Not a new PT entry: %x", Entry->signature); continue; } /* First partition contains partitions count */ if (Partition == 1) { PartitionEntries = be32_to_cpu(Entry->map_entries); } StartLba = be32_to_cpu(Entry->pblock_start); SizeLbs = be32_to_cpu(Entry->pblocks); if (0 && CompareMem("Apple_HFS", Entry->type, 10) == 0) Print(L"HFS partition (%d of %d) at LBA 0x%x size=%dM\n", Partition, PartitionEntries, StartLba, (UINT32)(MultU64x32(SizeLbs, SubBlockSize) / (1024 * 1024))); ZeroMem (&CdDev, sizeof (CdDev)); CdDev.Header.Type = MEDIA_DEVICE_PATH; CdDev.Header.SubType = MEDIA_CDROM_DP; SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev)); CdDev.BootEntry = 0; /* Convert from partition to media blocks */ CdDev.PartitionStart = StartLba / BlkPerSec; /* start, LBA */ CdDev.PartitionSize = SizeLbs / BlkPerSec; /* size, LBs */ Status = PartitionInstallChildHandle ( This, Handle, DiskIo, BlockIo, BlockIo2, DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &CdDev, CdDev.PartitionStart, CdDev.PartitionStart + CdDev.PartitionSize - 1, SubBlockSize, FALSE); if (!EFI_ERROR (Status)) { Found = EFI_SUCCESS; } } } while (0); done: FreePool (Block); return Found; }
EFI_STATUS BBTestUpdateCapsuleConformanceTest ( IN EFI_BB_TEST_PROTOCOL *This, IN VOID *ClientInterface, IN EFI_TEST_LEVEL TestLevel, IN EFI_HANDLE SupportHandle ) { EFI_STATUS Status; EFI_STANDARD_TEST_LIBRARY_PROTOCOL *StandardLib; EFI_TEST_ASSERTION AssertionType; UINT8 *AllocatedBuffer; EFI_CAPSULE_HEADER *CapsuleHeaderArray[2]; // // Get the Standard Library Interface // Status = gtBS->HandleProtocol ( SupportHandle, &gEfiStandardTestLibraryGuid, &StandardLib ); if (EFI_ERROR(Status)) { return Status; } if (FALSE == CheckBBTestCanRunAndRecordAssertion ( StandardLib, L"RT.UpdateCapsule_Conf- UpdateCapsule_Conf it's not Supported in EFI", __FILE__, (UINTN)__LINE__ )) { return EFI_SUCCESS; } AllocatedBuffer = (UINT8 *)AllocatePool (sizeof(EFI_CAPSULE_HEADER)); if (EFI_ERROR(Status)) { StandardLib->RecordAssertion ( StandardLib, EFI_TEST_ASSERTION_FAILED, gTestGenericFailureGuid, L"RT.UpdateCapsule_conf - Allocate pages for EFI_CAPSULE_HEADER", L"%a:%d,Status - %r", __FILE__, (UINTN)__LINE__, Status ); return Status; } CapsuleHeaderArray[0] = (EFI_CAPSULE_HEADER *) (UINTN)AllocatedBuffer; CapsuleHeaderArray[0]->CapsuleGuid = mEfiCapsuleHeaderGuid; CapsuleHeaderArray[0]->HeaderSize = sizeof(EFI_CAPSULE_HEADER); CapsuleHeaderArray[0]->CapsuleImageSize = sizeof(EFI_CAPSULE_HEADER); CapsuleHeaderArray[1] = NULL; CapsuleHeaderArray[0]->Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; // When CapsuleCount is 0, the return status code should be EFI_INVALID_PARAMETER Status = gtRT->UpdateCapsule( CapsuleHeaderArray, 0, // invaild (EFI_PHYSICAL_ADDRESS ) 0 ); if (Status == EFI_INVALID_PARAMETER) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gMiscRuntimeServicesBBTestConformanceAssertionGuid001, L"RT.UpdateCapsule - invoke UpdateCapsule with invalid CapsuleCount - 0", L"%a:%d:Status - %r", __FILE__, __LINE__, Status ); // // when the flag is CAPSULE_FLAGS_PERSIST_ACROSS_RESET, ScatterGatherList can't be NULL. // CapsuleHeaderArray[0] = (EFI_CAPSULE_HEADER *) (UINTN)AllocatedBuffer; CapsuleHeaderArray[0]->CapsuleGuid = mEfiCapsuleHeaderGuid; CapsuleHeaderArray[0]->HeaderSize = sizeof(EFI_CAPSULE_HEADER); CapsuleHeaderArray[0]->CapsuleImageSize = sizeof(EFI_CAPSULE_HEADER); CapsuleHeaderArray[1] = NULL; CapsuleHeaderArray[0]->Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE; Status = gtRT->UpdateCapsule( CapsuleHeaderArray, 1, (EFI_PHYSICAL_ADDRESS ) 0 ); if (Status == EFI_INVALID_PARAMETER) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gMiscRuntimeServicesBBTestConformanceAssertionGuid002, L"RT.UpdateCapsule - invoke UpdateCapsule with invalid ScatterGatherList", L"%a:%d:Status - %r", __FILE__, __LINE__, Status ); // // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag must have // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well. // CapsuleHeaderArray[0] = (EFI_CAPSULE_HEADER *) (UINTN)AllocatedBuffer; CapsuleHeaderArray[0]->CapsuleGuid = mEfiCapsuleHeaderGuid; CapsuleHeaderArray[0]->HeaderSize = sizeof(EFI_CAPSULE_HEADER); CapsuleHeaderArray[0]->CapsuleImageSize = sizeof(EFI_CAPSULE_HEADER); CapsuleHeaderArray[1] = NULL; CapsuleHeaderArray[0]->Flags = CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE; Status = gtRT->UpdateCapsule( CapsuleHeaderArray, 1, (EFI_PHYSICAL_ADDRESS ) 0 ); if (Status == EFI_INVALID_PARAMETER) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gMiscRuntimeServicesBBTestConformanceAssertionGuid003, L"RT.UpdateCapsule - invoke UpdateCapsule with invalid Flags", L"%a:%d:Status - %r", __FILE__, (UINTN)__LINE__, Status ); // // A capsule which has the CAPSULE_FLAGS_INITIATE_RESET Flag must have // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well. // CapsuleHeaderArray[0] = (EFI_CAPSULE_HEADER *) (UINTN)AllocatedBuffer; CapsuleHeaderArray[0]->CapsuleGuid = mEfiCapsuleHeaderGuid; CapsuleHeaderArray[0]->HeaderSize = sizeof(EFI_CAPSULE_HEADER); CapsuleHeaderArray[0]->CapsuleImageSize = sizeof(EFI_CAPSULE_HEADER); CapsuleHeaderArray[1] = NULL; CapsuleHeaderArray[0]->Flags = CAPSULE_FLAGS_INITIATE_RESET; Status = gtRT->UpdateCapsule( CapsuleHeaderArray, 1, (EFI_PHYSICAL_ADDRESS ) 0 ); if (Status == EFI_INVALID_PARAMETER) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gMiscRuntimeServicesBBTestConformanceAssertionGuid005, L"RT.UpdateCapsule - invoke UpdateCapsule with invalid Flags", L"%a:%d:Status - %r", __FILE__, (UINTN)__LINE__, Status ); FreePool(AllocatedBuffer); return EFI_SUCCESS; }
/** Install child handles if the Handle supports GPT partition structure. @param[in] This Calling context. @param[in] Handle Parent Handle. @param[in] DiskIo Parent DiskIo interface. @param[in] BlockIo Parent BlockIo interface. @param[in] BlockIo2 Parent BlockIo2 interface. @param[in] DevicePath Parent Device Path. @retval EFI_SUCCESS Valid GPT disk. @retval EFI_MEDIA_CHANGED Media changed Detected. @retval other Not a valid GPT disk. **/ EFI_STATUS PartitionInstallGptChildHandles ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_STATUS Status; UINT32 BlockSize; EFI_LBA LastBlock; MASTER_BOOT_RECORD *ProtectiveMbr; EFI_PARTITION_TABLE_HEADER *PrimaryHeader; EFI_PARTITION_TABLE_HEADER *BackupHeader; EFI_PARTITION_ENTRY *PartEntry; EFI_PARTITION_ENTRY *Entry; EFI_PARTITION_ENTRY_STATUS *PEntryStatus; UINTN Index; EFI_STATUS GptValidStatus; HARDDRIVE_DEVICE_PATH HdDev; UINT32 MediaId; VBoxLogFlowFuncMarkDP(DevicePath); ProtectiveMbr = NULL; PrimaryHeader = NULL; BackupHeader = NULL; PartEntry = NULL; PEntryStatus = NULL; BlockSize = BlockIo->Media->BlockSize; LastBlock = BlockIo->Media->LastBlock; MediaId = BlockIo->Media->MediaId; DEBUG ((EFI_D_INFO, " BlockSize : %d \n", BlockSize)); DEBUG ((EFI_D_INFO, " LastBlock : %lx \n", LastBlock)); GptValidStatus = EFI_NOT_FOUND; // // Allocate a buffer for the Protective MBR // ProtectiveMbr = AllocatePool (BlockSize); if (ProtectiveMbr == NULL) { return EFI_NOT_FOUND; } // // Read the Protective MBR from LBA #0 // Status = DiskIo->ReadDisk ( DiskIo, MediaId, 0, BlockSize, ProtectiveMbr ); if (EFI_ERROR (Status)) { GptValidStatus = Status; goto Done; } // // Verify that the Protective MBR is valid // for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) { if (ProtectiveMbr->Partition[Index].BootIndicator == 0x00 && ProtectiveMbr->Partition[Index].OSIndicator == PMBR_GPT_PARTITION && UNPACK_UINT32 (ProtectiveMbr->Partition[Index].StartingLBA) == 1 ) { break; } } if (Index == MAX_MBR_PARTITIONS) { goto Done; } // // Allocate the GPT structures // PrimaryHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER)); if (PrimaryHeader == NULL) { goto Done; } BackupHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER)); if (BackupHeader == NULL) { goto Done; } // // Check primary and backup partition tables // if (!PartitionValidGptTable (BlockIo, DiskIo, PRIMARY_PART_HEADER_LBA, PrimaryHeader)) { DEBUG ((EFI_D_INFO, " Not Valid primary partition table\n")); if (!PartitionValidGptTable (BlockIo, DiskIo, LastBlock, BackupHeader)) { DEBUG ((EFI_D_INFO, " Not Valid backup partition table\n")); goto Done; } else { DEBUG ((EFI_D_INFO, " Valid backup partition table\n")); DEBUG ((EFI_D_INFO, " Restore primary partition table by the backup\n")); if (!PartitionRestoreGptTable (BlockIo, DiskIo, BackupHeader)) { DEBUG ((EFI_D_INFO, " Restore primary partition table error\n")); } if (PartitionValidGptTable (BlockIo, DiskIo, BackupHeader->AlternateLBA, PrimaryHeader)) { DEBUG ((EFI_D_INFO, " Restore backup partition table success\n")); } } } else if (!PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) { DEBUG ((EFI_D_INFO, " Valid primary and !Valid backup partition table\n")); DEBUG ((EFI_D_INFO, " Restore backup partition table by the primary\n")); if (!PartitionRestoreGptTable (BlockIo, DiskIo, PrimaryHeader)) { DEBUG ((EFI_D_INFO, " Restore backup partition table error\n")); } if (PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) { DEBUG ((EFI_D_INFO, " Restore backup partition table success\n")); } } DEBUG ((EFI_D_INFO, " Valid primary and Valid backup partition table\n")); // // Read the EFI Partition Entries // PartEntry = AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry); if (PartEntry == NULL) { DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); goto Done; } Status = DiskIo->ReadDisk ( DiskIo, MediaId, MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockSize), PrimaryHeader->NumberOfPartitionEntries * (PrimaryHeader->SizeOfPartitionEntry), PartEntry ); if (EFI_ERROR (Status)) { GptValidStatus = Status; DEBUG ((EFI_D_ERROR, " Partition Entry ReadDisk error\n")); goto Done; } DEBUG ((EFI_D_INFO, " Partition entries read block success\n")); DEBUG ((EFI_D_INFO, " Number of partition entries: %d\n", PrimaryHeader->NumberOfPartitionEntries)); PEntryStatus = AllocateZeroPool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY_STATUS)); if (PEntryStatus == NULL) { DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); goto Done; } // // Check the integrity of partition entries // PartitionCheckGptEntry (PrimaryHeader, PartEntry, PEntryStatus); // // If we got this far the GPT layout of the disk is valid and we should return true // GptValidStatus = EFI_SUCCESS; // // Create child device handles // for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) { Entry = (EFI_PARTITION_ENTRY *) ((UINT8 *) PartEntry + Index * PrimaryHeader->SizeOfPartitionEntry); if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid) || PEntryStatus[Index].OutOfRange || PEntryStatus[Index].Overlap || PEntryStatus[Index].OsSpecific ) { // // Don't use null EFI Partition Entries, Invalid Partition Entries or OS specific // partition Entries // continue; } ZeroMem (&HdDev, sizeof (HdDev)); HdDev.Header.Type = MEDIA_DEVICE_PATH; HdDev.Header.SubType = MEDIA_HARDDRIVE_DP; SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev)); HdDev.PartitionNumber = (UINT32) Index + 1; HdDev.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER; HdDev.SignatureType = SIGNATURE_TYPE_GUID; HdDev.PartitionStart = Entry->StartingLBA; HdDev.PartitionSize = Entry->EndingLBA - Entry->StartingLBA + 1; CopyMem (HdDev.Signature, &Entry->UniquePartitionGUID, sizeof (EFI_GUID)); DEBUG ((EFI_D_INFO, " Index : %d\n", (UINT32) Index)); DEBUG ((EFI_D_INFO, " Start LBA : %lx\n", (UINT64) HdDev.PartitionStart)); DEBUG ((EFI_D_INFO, " End LBA : %lx\n", (UINT64) Entry->EndingLBA)); DEBUG ((EFI_D_INFO, " Partition size: %lx\n", (UINT64) HdDev.PartitionSize)); DEBUG ((EFI_D_INFO, " Start : %lx", MultU64x32 (Entry->StartingLBA, BlockSize))); DEBUG ((EFI_D_INFO, " End : %lx\n", MultU64x32 (Entry->EndingLBA, BlockSize))); Status = PartitionInstallChildHandle ( This, Handle, DiskIo, BlockIo, BlockIo2, DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &HdDev, Entry->StartingLBA, Entry->EndingLBA, BlockSize, CompareGuid(&Entry->PartitionTypeGUID, &gEfiPartTypeSystemPartGuid) ); } DEBUG ((EFI_D_INFO, "Prepare to Free Pool\n")); Done: if (ProtectiveMbr != NULL) { FreePool (ProtectiveMbr); } if (PrimaryHeader != NULL) { FreePool (PrimaryHeader); } if (BackupHeader != NULL) { FreePool (BackupHeader); } if (PartEntry != NULL) { FreePool (PartEntry); } if (PEntryStatus != NULL) { FreePool (PEntryStatus); } return GptValidStatus; }
/** Produces and returns an RNG value using either the default or specified RNG algorithm. @param[in] This A pointer to the EFI_RNG_PROTOCOL instance. @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that identifies the RNG algorithm to use. May be NULL in which case the function will use its default RNG algorithm. @param[in] RNGValueLength The length in bytes of the memory buffer pointed to by RNGValue. The driver shall return exactly this numbers of bytes. @param[out] RNGValue A caller-allocated memory buffer filled by the driver with the resulting RNG value. @retval EFI_SUCCESS The RNG value was returned successfully. @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm is not supported by this driver. @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due to a hardware or firmware error. @retval EFI_NOT_READY There is not enough random data available to satisfy the length requested by RNGValueLength. @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is zero. **/ STATIC EFI_STATUS EFIAPI VirtioRngGetRNG ( IN EFI_RNG_PROTOCOL *This, IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL IN UINTN RNGValueLength, OUT UINT8 *RNGValue ) { VIRTIO_RNG_DEV *Dev; DESC_INDICES Indices; volatile UINT8 *Buffer; UINTN Index; UINT32 Len; UINT32 BufferSize; EFI_STATUS Status; EFI_PHYSICAL_ADDRESS DeviceAddress; VOID *Mapping; if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) { return EFI_INVALID_PARAMETER; } // // We only support the raw algorithm, so reject requests for anything else // if (RNGAlgorithm != NULL && !CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) { return EFI_UNSUPPORTED; } Buffer = (volatile UINT8 *)AllocatePool (RNGValueLength); if (Buffer == NULL) { return EFI_DEVICE_ERROR; } Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This); // // Map Buffer's system phyiscal address to device address // Status = VirtioMapAllBytesInSharedBuffer ( Dev->VirtIo, VirtioOperationBusMasterWrite, (VOID *)Buffer, RNGValueLength, &DeviceAddress, &Mapping ); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto FreeBuffer; } // // The Virtio RNG device may return less data than we asked it to, and can // only return MAX_UINT32 bytes per invocation. So loop as long as needed to // get all the entropy we were asked for. // for (Index = 0; Index < RNGValueLength; Index += Len) { BufferSize = (UINT32)MIN (RNGValueLength - Index, (UINTN)MAX_UINT32); VirtioPrepare (&Dev->Ring, &Indices); VirtioAppendDesc (&Dev->Ring, DeviceAddress + Index, BufferSize, VRING_DESC_F_WRITE, &Indices); if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) != EFI_SUCCESS) { Status = EFI_DEVICE_ERROR; goto UnmapBuffer; } ASSERT (Len > 0); ASSERT (Len <= BufferSize); } // // Unmap the device buffer before accessing it. // Status = Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto FreeBuffer; } for (Index = 0; Index < RNGValueLength; Index++) { RNGValue[Index] = Buffer[Index]; } Status = EFI_SUCCESS; UnmapBuffer: // // If we are reached here due to the error then unmap the buffer otherwise // the buffer is already unmapped after VirtioFlush(). // if (EFI_ERROR (Status)) { Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping); } FreeBuffer: FreePool ((VOID *)Buffer); return Status; }
EFI_STATUS EFIAPI WinNtBusDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) /*++ Routine Description: Arguments: Returns: None --*/ // TODO: This - add argument and description to function comment // TODO: ControllerHandle - add argument and description to function comment // TODO: RemainingDevicePath - add argument and description to function comment // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment // TODO: EFI_SUCCESS - add return value to function comment { EFI_STATUS Status; EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; WIN_NT_BUS_DEVICE *WinNtBusDevice; WIN_NT_IO_DEVICE *WinNtDevice; UINTN Index; CHAR16 *StartString; CHAR16 *SubString; UINT16 Count; UINTN StringSize; UINT16 ComponentName[MAX_NT_ENVIRNMENT_VARIABLE_LENGTH]; WIN_NT_VENDOR_DEVICE_PATH_NODE *Node; BOOLEAN CreateDevice; CHAR16 *TempStr; CHAR16 *PcdTempStr; UINTN TempStrSize; Status = EFI_UNSUPPORTED; // // Grab the protocols we need // Status = gBS->OpenProtocol ( ControllerHandle, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { return Status; } Status = gBS->OpenProtocol ( ControllerHandle, &gEfiWinNtThunkProtocolGuid, (VOID **) &WinNtThunk, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { return Status; } if (Status != EFI_ALREADY_STARTED) { WinNtBusDevice = AllocatePool (sizeof (WIN_NT_BUS_DEVICE)); if (WinNtBusDevice == NULL) { return EFI_OUT_OF_RESOURCES; } WinNtBusDevice->Signature = WIN_NT_BUS_DEVICE_SIGNATURE; WinNtBusDevice->ControllerNameTable = NULL; AddUnicodeString2 ( "eng", gWinNtBusDriverComponentName.SupportedLanguages, &WinNtBusDevice->ControllerNameTable, L"Windows Bus Controller", TRUE ); AddUnicodeString2 ( "en", gWinNtBusDriverComponentName2.SupportedLanguages, &WinNtBusDevice->ControllerNameTable, L"Windows Bus Controller", FALSE ); Status = gBS->InstallMultipleProtocolInterfaces ( &ControllerHandle, &gWinNtBusDriverGuid, WinNtBusDevice, NULL ); if (EFI_ERROR (Status)) { FreeUnicodeStringTable (WinNtBusDevice->ControllerNameTable); FreePool (WinNtBusDevice); return Status; } } // // Loop on the Variable list. Parse each variable to produce a set of handles that // represent virtual hardware devices. // for (Index = 0; Index < NT_PCD_ARRAY_SIZE; Index++) { PcdTempStr = (VOID *)LibPcdGetPtr (mPcdEnvironment[Index].Token); ASSERT (PcdTempStr != NULL); TempStrSize = StrLen (PcdTempStr); TempStr = AllocateMemory (((TempStrSize + 1) * sizeof (CHAR16))); StrCpy (TempStr, PcdTempStr); StartString = TempStr; // // Parse the envirnment variable into sub strings using '!' as a delimator. // Each substring needs it's own handle to be added to the system. This code // does not understand the sub string. Thats the device drivers job. // Count = 0; while (*StartString != '\0') { // // Find the end of the sub string // SubString = StartString; while (*SubString != '\0' && *SubString != '!') { SubString++; } if (*SubString == '!') { // // Replace token with '\0' to make sub strings. If this is the end // of the string SubString will already point to NULL. // *SubString = '\0'; SubString++; } CreateDevice = TRUE; if (RemainingDevicePath != NULL) { CreateDevice = FALSE; // // Check if RemainingDevicePath is the End of Device Path Node, // if yes, don't create any child device // if (!IsDevicePathEnd (RemainingDevicePath)) { // // If RemainingDevicePath isn't the End of Device Path Node, // check its validation // Node = (WIN_NT_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath; if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH && Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP && DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE) ) { if (CompareGuid (&Node->VendorDevicePath.Guid, mPcdEnvironment[Index].DevicePathGuid) && Node->Instance == Count ) { CreateDevice = TRUE; } } } } if (CreateDevice) { // // Allocate instance structure, and fill in parent information. // WinNtDevice = AllocateMemory (sizeof (WIN_NT_IO_DEVICE)); if (WinNtDevice == NULL) { return EFI_OUT_OF_RESOURCES; } WinNtDevice->Handle = NULL; WinNtDevice->ControllerHandle = ControllerHandle; WinNtDevice->ParentDevicePath = ParentDevicePath; WinNtDevice->WinNtIo.WinNtThunk = WinNtThunk; // // Plus 2 to account for the NULL at the end of the Unicode string // StringSize = (UINTN) ((UINT8 *) SubString - (UINT8 *) StartString) + sizeof (CHAR16); WinNtDevice->WinNtIo.EnvString = AllocateMemory (StringSize); if (WinNtDevice->WinNtIo.EnvString != NULL) { CopyMem (WinNtDevice->WinNtIo.EnvString, StartString, StringSize); } WinNtDevice->ControllerNameTable = NULL; WinNtThunk->SPrintf (ComponentName, sizeof (ComponentName), L"%s", WinNtDevice->WinNtIo.EnvString); WinNtDevice->DevicePath = WinNtBusCreateDevicePath ( ParentDevicePath, mPcdEnvironment[Index].DevicePathGuid, Count ); if (WinNtDevice->DevicePath == NULL) { FreePool (WinNtDevice); return EFI_OUT_OF_RESOURCES; } AddUnicodeString2 ( "eng", gWinNtBusDriverComponentName.SupportedLanguages, &WinNtDevice->ControllerNameTable, ComponentName, TRUE ); AddUnicodeString2 ( "en", gWinNtBusDriverComponentName2.SupportedLanguages, &WinNtDevice->ControllerNameTable, ComponentName, FALSE ); WinNtDevice->WinNtIo.TypeGuid = mPcdEnvironment[Index].DevicePathGuid; WinNtDevice->WinNtIo.InstanceNumber = Count; WinNtDevice->Signature = WIN_NT_IO_DEVICE_SIGNATURE; Status = gBS->InstallMultipleProtocolInterfaces ( &WinNtDevice->Handle, &gEfiDevicePathProtocolGuid, WinNtDevice->DevicePath, &gEfiWinNtIoProtocolGuid, &WinNtDevice->WinNtIo, NULL ); if (EFI_ERROR (Status)) { FreeUnicodeStringTable (WinNtDevice->ControllerNameTable); FreePool (WinNtDevice); } else { // // Open For Child Device // Status = gBS->OpenProtocol ( ControllerHandle, &gEfiWinNtThunkProtocolGuid, (VOID **) &WinNtThunk, This->DriverBindingHandle, WinNtDevice->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); } } // // Parse Next sub string. This will point to '\0' if we are at the end. // Count++; StartString = SubString; } FreePool (TempStr); } return EFI_SUCCESS; }