STATIC EFI_STATUS CreatePlatformBootOptionFromPath ( IN CHAR16 *PathStr, IN CHAR16 *Description, IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *BootOption ) { EFI_STATUS Status; EFI_DEVICE_PATH *DevicePath; DevicePath = (EFI_DEVICE_PATH *)ConvertTextToDevicePath (PathStr); ASSERT (DevicePath != NULL); Status = EfiBootManagerInitializeLoadOption ( BootOption, LoadOptionNumberUnassigned, LoadOptionTypeBoot, LOAD_OPTION_ACTIVE, Description, DevicePath, NULL, 0 ); FreePool (DevicePath); return Status; }
/* Initialise: Open the Android NVM device and find the partitions on it. Save them in a list along with the "PartitionName" fields for their GPT entries. We will use these partition names as the key in ArmFastbootPlatformFlashPartition. */ EFI_STATUS ArmFastbootPlatformInit ( VOID ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *FlashDevicePath; EFI_DEVICE_PATH_PROTOCOL *FlashDevicePathDup; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *NextNode; HARDDRIVE_DEVICE_PATH *PartitionNode; UINTN NumHandles; EFI_HANDLE *AllHandles; UINTN LoopIndex; EFI_HANDLE FlashHandle; EFI_BLOCK_IO_PROTOCOL *FlashBlockIo; EFI_PARTITION_ENTRY *PartitionEntries; FASTBOOT_PARTITION_LIST *Entry; InitializeListHead (&mPartitionListHead); // // Get EFI_HANDLES for all the partitions on the block devices pointed to by // PcdFastbootFlashDevicePath, also saving their GPT partition labels. // There's no way to find all of a device's children, so we get every handle // in the system supporting EFI_BLOCK_IO_PROTOCOL and then filter out ones // that don't represent partitions on the flash device. // FlashDevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdAndroidFastbootNvmDevicePath)); // // Open the Disk IO protocol on the flash device - this will be used to read // partition names out of the GPT entries // // Create another device path pointer because LocateDevicePath will modify it. FlashDevicePathDup = FlashDevicePath; Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &FlashDevicePathDup, &FlashHandle); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Warning: Couldn't locate Android NVM device (status: %r)\n", Status)); // Failing to locate partitions should not prevent to do other Android FastBoot actions return EFI_SUCCESS; } Status = gBS->OpenProtocol ( FlashHandle, &gEfiBlockIoProtocolGuid, (VOID **) &FlashBlockIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Fastboot platform: Couldn't open Android NVM device (status: %r)\n", Status)); return EFI_DEVICE_ERROR; } // Read the GPT partition entry array into memory so we can get the partition names Status = ReadPartitionEntries (FlashBlockIo, &PartitionEntries); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Warning: Failed to read partitions from Android NVM device (status: %r)\n", Status)); // Failing to locate partitions should not prevent to do other Android FastBoot actions return EFI_SUCCESS; } // Get every Block IO protocol instance installed in the system Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &NumHandles, &AllHandles ); ASSERT_EFI_ERROR (Status); // Filter out handles that aren't children of the flash device for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) { // Get the device path for the handle Status = gBS->OpenProtocol ( AllHandles[LoopIndex], &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); ASSERT_EFI_ERROR (Status); // Check if it is a sub-device of the flash device if (!CompareMem (DevicePath, FlashDevicePath, FLASH_DEVICE_PATH_SIZE (FlashDevicePath))) { // Device path starts with path of flash device. Check it isn't the flash // device itself. NextNode = NextDevicePathNode (DevicePath); if (IsDevicePathEndType (NextNode)) { continue; } // Assert that this device path node represents a partition. ASSERT (NextNode->Type == MEDIA_DEVICE_PATH && NextNode->SubType == MEDIA_HARDDRIVE_DP); PartitionNode = (HARDDRIVE_DEVICE_PATH *) NextNode; // Assert that the partition type is GPT. ReadPartitionEntries checks for // presence of a GPT, so we should never find MBR partitions. // ("MBRType" is a misnomer - this field is actually called "Partition // Format") ASSERT (PartitionNode->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER); // The firmware may install a handle for "partition 0", representing the // whole device. Ignore it. if (PartitionNode->PartitionNumber == 0) { continue; } // // Add the partition handle to the list // // Create entry Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST)); if (Entry == NULL) { Status = EFI_OUT_OF_RESOURCES; FreePartitionList (); goto Exit; } // Copy handle and partition name Entry->PartitionHandle = AllHandles[LoopIndex]; StrnCpy ( Entry->PartitionName, PartitionEntries[PartitionNode->PartitionNumber - 1].PartitionName, // Partition numbers start from 1. PARTITION_NAME_MAX_LENGTH ); InsertTailList (&mPartitionListHead, &Entry->Link); // Print a debug message if the partition label is empty or looks like // garbage. if (!IS_ALPHA (Entry->PartitionName[0])) { DEBUG ((EFI_D_ERROR, "Warning: Partition %d doesn't seem to have a GPT partition label. " "You won't be able to flash it with Fastboot.\n", PartitionNode->PartitionNumber )); } } } Exit: FreePool (PartitionEntries); FreePool (FlashDevicePath); FreePool (AllHandles); return Status; }
/** Function to parse the Data by the type of Data, and save in the Buffer. @param[in] Data A pointer to a buffer to be parsed. @param[out] Buffer A pointer to a buffer to hold the return data. @param[in,out] BufferSize On input, indicates the size of Buffer in bytes. On output,indicates the size of data return in Buffer. Or the size in bytes of the buffer needed to obtain. @retval EFI_INVALID_PARAMETER The Buffer or BufferSize is NULL. @retval EFI_BUFFER_TOO_SMALL The Buffer is too small to hold the data. @retval EFI_OUT_OF_RESOURCES A memory allcation failed. @retval EFI_SUCCESS The Data parsed successful and save in the Buffer. **/ EFI_STATUS ParseParameterData ( IN CONST CHAR16 *Data, OUT VOID *Buffer, IN OUT UINTN *BufferSize ) { UINT64 HexNumber; UINTN HexNumberLen; UINTN Size; CHAR8 *AsciiBuffer; DATA_TYPE DataType; EFI_DEVICE_PATH_PROTOCOL *DevPath; EFI_STATUS Status; HexNumber = 0; HexNumberLen = 0; Size = 0; AsciiBuffer = NULL; DevPath = NULL; Status = EFI_SUCCESS; if (Data == NULL || BufferSize == NULL) { return EFI_INVALID_PARAMETER; } DataType = TestDataType (Data); if (DataType == DataTypeHexNumber) { // // hex number // StrHexToUint64S (Data + 2, NULL, &HexNumber); HexNumberLen = StrLen (Data + 2); if (HexNumberLen >= 1 && HexNumberLen <= 2) { Size = 1; } else if (HexNumberLen >= 3 && HexNumberLen <= 4) { Size = 2; } else if (HexNumberLen >= 5 && HexNumberLen <= 8) { Size = 4; } else if (HexNumberLen >= 9 && HexNumberLen <= 16) { Size = 8; } if (Buffer != NULL && *BufferSize >= Size) { CopyMem(Buffer, (VOID *)&HexNumber, Size); } else { Status = EFI_BUFFER_TOO_SMALL; } *BufferSize = Size; } else if (DataType == DataTypeHexArray) { // // hex array // if (*Data == L'H') { Data = Data + 1; } Size = StrLen (Data) / 2; if (Buffer != NULL && *BufferSize >= Size) { StrHexToBytes(Data, StrLen (Data), (UINT8 *)Buffer, Size); } else { Status = EFI_BUFFER_TOO_SMALL; } *BufferSize = Size; } else if (DataType == DataTypeAscii) { // // ascii text // if (*Data == L'S') { Data = Data + 1; } AsciiBuffer = AllocateZeroPool (StrSize (Data) / 2); if (AsciiBuffer == NULL) { Status = EFI_OUT_OF_RESOURCES; } else { AsciiSPrint (AsciiBuffer, StrSize (Data) / 2, "%s", (CHAR8 *)Data); Size = StrSize (Data) / 2 - 1; if (Buffer != NULL && *BufferSize >= Size) { CopyMem (Buffer, AsciiBuffer, Size); } else { Status = EFI_BUFFER_TOO_SMALL; } *BufferSize = Size; } SHELL_FREE_NON_NULL (AsciiBuffer); } else if (DataType == DataTypeUnicode) { // // unicode text // if (*Data == L'L') { Data = Data + 1; } Size = StrSize (Data) - sizeof (CHAR16); if (Buffer != NULL && *BufferSize >= Size) { CopyMem (Buffer, Data, Size); } else { Status = EFI_BUFFER_TOO_SMALL; } *BufferSize = Size; } else if (DataType == DataTypeDevicePath) { if (*Data == L'P') { Data = Data + 1; } else if (StrnCmp (Data, L"--", 2) == 0) { Data = Data + 2; } DevPath = ConvertTextToDevicePath (Data); if (DevPath == NULL) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_DPFT), gShellDebug1HiiHandle, L"setvar"); Status = EFI_INVALID_PARAMETER; } else { Size = GetDevicePathSize (DevPath); if (Buffer != NULL && *BufferSize >= Size) { CopyMem (Buffer, DevPath, Size); } else { Status = EFI_BUFFER_TOO_SMALL; } *BufferSize = Size; } SHELL_FREE_NON_NULL (DevPath); } else { Status = EFI_INVALID_PARAMETER; } return Status; }
/** Function for 'setvar' command. @param[in] ImageHandle Handle to the Image (NULL if Internal). @param[in] SystemTable Pointer to the System Table (NULL if Internal). **/ SHELL_STATUS EFIAPI ShellCommandRunSetVar ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; LIST_ENTRY *Package; CHAR16 *ProblemParam; SHELL_STATUS ShellStatus; CONST CHAR16 *VariableName; CONST CHAR16 *Data; EFI_GUID Guid; CONST CHAR16 *StringGuid; UINT32 Attributes; UINT32 Attributes2; VOID *Buffer; UINTN Size; UINTN LoopVar; EFI_DEVICE_PATH_PROTOCOL *DevPath; ShellStatus = SHELL_SUCCESS; Status = EFI_SUCCESS; Buffer = NULL; Size = 0; Attributes = 0; DevPath = NULL; // // initialize the shell lib (we must be in non-auto-init...) // Status = ShellInitialize(); ASSERT_EFI_ERROR(Status); Status = CommandInit(); ASSERT_EFI_ERROR(Status); // // parse the command line // Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); if (EFI_ERROR(Status)) { if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam); FreePool(ProblemParam); ShellStatus = SHELL_INVALID_PARAMETER; } else { ASSERT(FALSE); } } else { if (ShellCommandLineGetCount(Package) < 2) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle); ShellStatus = SHELL_INVALID_PARAMETER; } else if (ShellCommandLineGetCount(Package) > 3) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle); ShellStatus = SHELL_INVALID_PARAMETER; } else { VariableName = ShellCommandLineGetRawValue(Package, 1); Data = ShellCommandLineGetRawValue(Package, 2); if (!ShellCommandLineGetFlag(Package, L"-guid")){ CopyGuid(&Guid, &gEfiGlobalVariableGuid); } else { StringGuid = ShellCommandLineGetValue(Package, L"-guid"); Status = ConvertStringToGuid(StringGuid, &Guid); if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, StringGuid); ShellStatus = SHELL_INVALID_PARAMETER; } } if (Data == NULL) { // // Display what's there // Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer); if (Status == EFI_BUFFER_TOO_SMALL) { Buffer = AllocateZeroPool(Size); Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer); } if (!EFI_ERROR(Status)&& Buffer != NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_PRINT), gShellDebug1HiiHandle, &Guid, VariableName, Size); for (LoopVar = 0 ; LoopVar < Size ; LoopVar++) { ShellPrintEx(-1, -1, L"%02x ", ((UINT8*)Buffer)[LoopVar]); } ShellPrintEx(-1, -1, L"\r\n"); } else { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_GET), gShellDebug1HiiHandle, &Guid, VariableName, Status); ShellStatus = SHELL_ACCESS_DENIED; } } else if (StrCmp(Data, L"=") == 0) { // // Delete what's there! // Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, 0, NULL); if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, &Guid, VariableName, Status); ShellStatus = SHELL_ACCESS_DENIED; } else { ASSERT(ShellStatus == SHELL_SUCCESS); } } else { if (Data[0] == L'=') { Data++; } // // Change what's there // if (ShellCommandLineGetFlag(Package, L"-bs")) { Attributes |= EFI_VARIABLE_BOOTSERVICE_ACCESS; } if (ShellCommandLineGetFlag(Package, L"-rt")) { Attributes |= EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS; } if (ShellCommandLineGetFlag(Package, L"-nv")) { Attributes |= EFI_VARIABLE_NON_VOLATILE; } if (ShellIsHexOrDecimalNumber(Data, TRUE, FALSE)) { if (StrLen(Data) % 2 != 0) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, Data); ShellStatus = SHELL_INVALID_PARAMETER; } else { // // arbitrary buffer // Buffer = AllocateZeroPool((StrLen(Data) / 2)); if (Buffer == NULL) { Status = EFI_OUT_OF_RESOURCES; } else { for (LoopVar = 0 ; LoopVar < (StrLen(Data) / 2) ; LoopVar++) { ((UINT8*)Buffer)[LoopVar] = (UINT8)(HexCharToUintn(Data[LoopVar*2]) * 16); ((UINT8*)Buffer)[LoopVar] = (UINT8)(((UINT8*)Buffer)[LoopVar] + HexCharToUintn(Data[LoopVar*2+1])); } Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, StrLen(Data) / 2, Buffer); } if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, &Guid, VariableName, Status); ShellStatus = SHELL_ACCESS_DENIED; } else { ASSERT(ShellStatus == SHELL_SUCCESS); } } } else if (StrnCmp(Data, L"\"", 1) == 0) { Size = 0; Attributes2 = 0; Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes2, &Size, Buffer); if (Status == EFI_BUFFER_TOO_SMALL) { Buffer = AllocateZeroPool(Size); Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes2, &Size, Buffer); if (Buffer != NULL) { FreePool(Buffer); } Attributes = Attributes2; } // // ascii text // Data++; Buffer = AllocateZeroPool(StrSize(Data) / 2); if (Buffer == NULL) { Status = EFI_OUT_OF_RESOURCES; } else { AsciiSPrint(Buffer, StrSize(Data) / 2, "%s", Data); ((CHAR8*)Buffer)[AsciiStrLen(Buffer)-1] = CHAR_NULL; Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, AsciiStrSize(Buffer)-sizeof(CHAR8), Buffer); } if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, &Guid, VariableName, Status); ShellStatus = SHELL_ACCESS_DENIED; } else { ASSERT(ShellStatus == SHELL_SUCCESS); } } else if (StrnCmp(Data, L"L\"", 2) == 0) { // // ucs2 text // Data++; Data++; Buffer = AllocateZeroPool(StrSize(Data)); if (Buffer == NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle); ShellStatus = SHELL_OUT_OF_RESOURCES; } else { UnicodeSPrint(Buffer, StrSize(Data), L"%s", Data); ((CHAR16*)Buffer)[StrLen(Buffer)-1] = CHAR_NULL; Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, StrSize(Buffer)-sizeof(CHAR16), Buffer); if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, &Guid, VariableName, Status); ShellStatus = SHELL_ACCESS_DENIED; } else { ASSERT(ShellStatus == SHELL_SUCCESS); } } } else if (StrnCmp(Data, L"--", 2) == 0) { // // device path in text format // Data++; Data++; DevPath = ConvertTextToDevicePath(Data); if (DevPath == NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_DPFT), gShellDebug1HiiHandle, Status); ShellStatus = SHELL_INVALID_PARAMETER; } else { Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, GetDevicePathSize(DevPath), DevPath); if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, &Guid, VariableName, Status); ShellStatus = SHELL_ACCESS_DENIED; } else { ASSERT(ShellStatus == SHELL_SUCCESS); } } } else { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Data); ShellStatus = SHELL_INVALID_PARAMETER; } } } ShellCommandLineFreeVarList (Package); } if (Buffer != NULL) { FreePool(Buffer); } if (DevPath != NULL) { FreePool(DevPath); } return (ShellStatus); }