Message ID | 1487170499-22374-6-git-send-email-haojian.zhuang@linaro.org |
---|---|
State | New |
Headers | show |
Series | add drivers for Android Fastboot App on HiKey | expand |
On Wed, Feb 15, 2017 at 10:54:59PM +0800, Haojian Zhuang wrote: > Support HiKey Fastboot driver for Fastboot App. > I asked a few questions on v3, which I received no replies to. Here I asked: --- Question: I notice this version deletes the SPARSE_HEADER support, which was one of the main differences compared to VEXpress driver. Is this something you plan to introduce in future? --- > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org> > --- > Platforms/Hisilicon/HiKey/HiKey.dec | 1 + > .../HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c | 672 +++++++++++++++++++++ > .../HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf | 61 ++ > .../Hisilicon/HiKey/Include/Guid/HiKeyVariable.h | 24 + > 4 files changed, 758 insertions(+) > create mode 100644 Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c > create mode 100644 Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf > create mode 100644 Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h > > diff --git a/Platforms/Hisilicon/HiKey/HiKey.dec b/Platforms/Hisilicon/HiKey/HiKey.dec > index 537138e..17c6484 100644 > --- a/Platforms/Hisilicon/HiKey/HiKey.dec > +++ b/Platforms/Hisilicon/HiKey/HiKey.dec > @@ -30,6 +30,7 @@ > > [Guids.common] > gHiKeyTokenSpaceGuid = { 0x91148425, 0xcdd2, 0x4830, { 0x8b, 0xd0, 0xc6, 0x1c, 0x6d, 0xea, 0x36, 0x21 } } > + gHiKeyVariableGuid = { 0x66b8d063, 0x1daa, 0x4c60, { 0xb9, 0xf2, 0x55, 0x0d, 0x7e, 0xe1, 0x2f, 0x38 } } > > [PcdsFixedAtBuild.common] > gHiKeyTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath|L""|VOID*|0x00000001 > diff --git a/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c > new file mode 100644 > index 0000000..2597f7a > --- /dev/null > +++ b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c > @@ -0,0 +1,672 @@ > +/** @file > + > + Copyright (c) 2014, ARM Ltd. All rights reserved.<BR> > + Copyright (c) 2015-2017, Linaro. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > +**/ > + > +/* > + Implementation of the Android Fastboot Platform protocol, to be used by the > + Fastboot UEFI application, for Hisilicon HiKey platform. > +*/ > + > +#include <Protocol/AndroidFastbootPlatform.h> > +#include <Protocol/BlockIo.h> > +#include <Protocol/DiskIo.h> > +#include <Protocol/EraseBlock.h> > +#include <Protocol/SimpleTextOut.h> > + > +#include <Library/BaseLib.h> > +#include <Library/BaseMemoryLib.h> > +#include <Library/DebugLib.h> > +#include <Library/DevicePathLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Library/UefiRuntimeServicesTableLib.h> > +#include <Library/PrintLib.h> > +#include <Library/TimerLib.h> > + > +#include <Guid/HiKeyVariable.h> > + > +#define FLASH_DEVICE_PATH_SIZE(DevPath) ( GetDevicePathSize (DevPath) - \ > + sizeof (EFI_DEVICE_PATH_PROTOCOL)) > + > +#define PARTITION_NAME_MAX_LENGTH 72/2 > + > +#define IS_ALPHA(Char) (((Char) <= L'z' && (Char) >= L'a') || \ > + ((Char) <= L'Z' && (Char) >= L'Z')) > +#define IS_HEXCHAR(Char) (((Char) <= L'9' && (Char) >= L'0') || \ > + IS_ALPHA(Char)) > + > +#define SERIAL_NUMBER_LENGTH 16 > +#define BOOT_DEVICE_LENGTH 16 > + > +#define HIKEY_ERASE_SIZE (16 * 1024 * 1024) > +#define HIKEY_ERASE_BLOCKS (HIKEY_ERASE_SIZE / EFI_PAGE_SIZE) > +#define PARTITION_TYPE_STRING "partition-type" > +#define PARTITION_SIZE_STRING "partition-size" > +// length of a 12-byte hex string > +#define PARTITION_SIZE_LENGTH 12 > +#define PARTITION_NAME_LENGTH 36 // CHAR16 And here I asked: --- Where does this limit come from? Specification? --- > + > +/* > + * struct entry_head { > + * unsigned char magic[8]; // "ENTRYHDR" > + * unsigned char name[8]; // "primary"/"second" > + * unsigned int start_lba; > + * unsigned int count_lba; > + * unsigned int flag; > + * } > + * > + * ptable: > + * ------------------------------------------------------ > + * | head (primary) | content | head (second) | content | > + * ------------------------------------------------------ > + */ > + > +#define HIKEY_PTABLE_HEAD_MAGIC_LEN 8 > +#define HIKEY_PTABLE_HEAD_NAME_LEN 8 > +#define HIKEY_PTABLE_HEAD_SIZE 28 > +#define HIKEY_PTABLE_CONTENT_OFFSET 512 > + > + > +typedef struct _FASTBOOT_PARTITION_LIST { > + LIST_ENTRY Link; > + CHAR16 PartitionName[PARTITION_NAME_MAX_LENGTH]; > + EFI_HANDLE PartitionHandle; > + EFI_LBA Lba; > +} FASTBOOT_PARTITION_LIST; > + > +STATIC LIST_ENTRY mPartitionListHead; > + > +/* > + Helper to free the partition list > +*/ > +STATIC > +VOID > +FreePartitionList ( > + VOID > + ) > +{ > + FASTBOOT_PARTITION_LIST *Entry; > + FASTBOOT_PARTITION_LIST *NextEntry; > + > + Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&mPartitionListHead); > + while (!IsNull (&mPartitionListHead, &Entry->Link)) { > + NextEntry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &Entry->Link); > + > + RemoveEntryList (&Entry->Link); > + FreePool (Entry); > + > + Entry = NextEntry; > + } > +} > +/* > + Read the PartitionName fields from the GPT partition entries, putting them > + into an allocated array that should later be freed. > +*/ > +STATIC > +EFI_STATUS > +ReadPartitionEntries ( > + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, > + OUT EFI_PARTITION_ENTRY **PartitionEntries > + ) > +{ > + UINTN EntrySize; > + UINTN NumEntries; > + UINTN BufferSize; > + UINT32 MediaId; > + EFI_PARTITION_TABLE_HEADER *GptHeader; > + EFI_STATUS Status; > + > + MediaId = BlockIo->Media->MediaId; > + > + // > + // Read size of Partition entry and number of entries from GPT header > + // > + > + GptHeader = AllocatePool (BlockIo->Media->BlockSize); > + if (GptHeader == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + Status = BlockIo->ReadBlocks (BlockIo, MediaId, 1, BlockIo->Media->BlockSize, GptHeader); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Check there is a GPT on the media > + if (GptHeader->Header.Signature != EFI_PTAB_HEADER_ID || > + GptHeader->MyLBA != 1) { > + DEBUG ((DEBUG_ERROR, > + "Fastboot platform: No GPT on flash. " > + "Fastboot on HiKey does not support MBR.\n" > + )); > + return EFI_DEVICE_ERROR; > + } > + > + EntrySize = GptHeader->SizeOfPartitionEntry; > + NumEntries = GptHeader->NumberOfPartitionEntries; > + > + FreePool (GptHeader); > + > + ASSERT (EntrySize != 0); > + ASSERT (NumEntries != 0); > + > + BufferSize = ALIGN_VALUE (EntrySize * NumEntries, BlockIo->Media->BlockSize); > + *PartitionEntries = AllocatePool (BufferSize); > + if (PartitionEntries == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + Status = BlockIo->ReadBlocks (BlockIo, MediaId, 2, BufferSize, (VOID *) *PartitionEntries); > + if (EFI_ERROR (Status)) { > + FreePool (PartitionEntries); > + return Status; > + } > + > + return Status; > +} > + > + > +STATIC > +EFI_STATUS > +CreateGptPartitionEntry ( > + IN EFI_HANDLE *AllHandles, > + IN UINTN LoopIndex, > + IN HARDDRIVE_DEVICE_PATH *PartitionNode, > + IN EFI_PARTITION_ENTRY *PartitionEntries > + ) > +{ > + FASTBOOT_PARTITION_LIST *Entry; > + > + // Create entry > + Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST)); > + if (Entry == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // 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 > + ); > + Entry->Lba = PartitionEntries[PartitionNode->PartitionNumber - 1].StartingLBA; > + 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 ((DEBUG_WARN, > + "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 > + )); > + } > + return EFI_SUCCESS; > +} > + > +STATIC > +EFI_STATUS > +CreatePartitionEntry ( > + IN EFI_HANDLE *AllHandles, > + IN UINTN LoopIndex, > + IN EFI_DEVICE_PATH_PROTOCOL *FlashDevicePath, > + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, > + IN EFI_PARTITION_ENTRY *PartitionEntries > + ) > +{ > + EFI_DEVICE_PATH_PROTOCOL *NextNode; > + FASTBOOT_PARTITION_LIST *Entry; > + HARDDRIVE_DEVICE_PATH *PartitionNode; > + > + // Fill out if it isn't a sub-device of the flash device > + if (CompareMem (DevicePath, FlashDevicePath, FLASH_DEVICE_PATH_SIZE (FlashDevicePath))) { > + return EFI_SUCCESS; > + } > + // Device path starts with path of flash device. Check it isn't the flash > + // device itself. > + NextNode = NextDevicePathNode (DevicePath); > + if (IsDevicePathEndType (NextNode)) { > + // Create entry > + Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST)); > + if (Entry == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // Copy handle and partition name > + Entry->PartitionHandle = AllHandles[LoopIndex]; > + StrCpy (Entry->PartitionName, L"ptable"); > + InsertTailList (&mPartitionListHead, &Entry->Link); > + return EFI_SUCCESS; > + } > + > + // 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) { > + return EFI_SUCCESS; > + } > + return CreateGptPartitionEntry (AllHandles, LoopIndex, PartitionNode, PartitionEntries); > +} > + > +/* > + 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 > + HiKeyFastbootPlatformFlashPartition. > +*/ > +STATIC > +EFI_STATUS > +HiKeyFastbootPlatformInit ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + EFI_DEVICE_PATH_PROTOCOL *FlashDevicePath; > + EFI_DEVICE_PATH_PROTOCOL *FlashDevicePathDup; > + EFI_DEVICE_PATH_PROTOCOL *DevicePath; > + UINTN NumHandles; > + EFI_HANDLE *AllHandles; > + UINTN LoopIndex; > + EFI_HANDLE FlashHandle; > + EFI_BLOCK_IO_PROTOCOL *FlashBlockIo; > + EFI_PARTITION_ENTRY *PartitionEntries; > + > + 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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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); > + > + Status = CreatePartitionEntry ( > + AllHandles, > + LoopIndex, > + FlashDevicePath, > + DevicePath, > + PartitionEntries > + ); > + if (EFI_ERROR (Status)) { > + FreePartitionList (); > + goto Exit; > + } > + } > + > +Exit: > + FreePool (PartitionEntries); > + FreePool (FlashDevicePath); > + FreePool (AllHandles); > + return Status; > + > +} > + > +STATIC > +VOID > +HiKeyFastbootPlatformUnInit ( > + VOID > + ) > +{ > + FreePartitionList (); > +} > + > +STATIC > +VOID * > +WritePartition ( > + IN VOID *Image, > + IN UINTN Size, > + IN EFI_DISK_IO_PROTOCOL *DiskIo, > + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, > + IN CHAR8 *Name > + ) > +{ > + UINT32 EntrySize, EntryOffset; > + EFI_STATUS Status; > + VOID *Buffer; > + > + Buffer = Image; > + // not a string with terminated '\0' > + if (AsciiStrnCmp (Buffer, "ENTRYHDR", HIKEY_PTABLE_HEAD_MAGIC_LEN) != 0) { > + DEBUG ((DEBUG_ERROR, "unknown ptable image\n")); > + return NULL; > + } > + Buffer += HIKEY_PTABLE_HEAD_MAGIC_LEN; > + // not a string with terminated '\0' > + if (AsciiStrnCmp (Buffer, Name, HIKEY_PTABLE_HEAD_NAME_LEN) != 0) { > + DEBUG ((DEBUG_ERROR, "unknown ptable image\n")); > + return NULL; > + } > + Buffer += HIKEY_PTABLE_HEAD_NAME_LEN; > + EntryOffset = *(UINT32 *)Buffer * BlockIo->Media->BlockSize; > + Buffer += sizeof (UINT32); > + EntrySize = *(UINT32 *)Buffer * BlockIo->Media->BlockSize; > + if ((EntrySize + HIKEY_PTABLE_CONTENT_OFFSET) > Size) { > + DEBUG ((DEBUG_ERROR, "Entry size doesn't match\n")); > + return NULL; > + } > + Buffer = Image + HIKEY_PTABLE_CONTENT_OFFSET; > + Status = DiskIo->WriteDisk (DiskIo, BlockIo->Media->MediaId, EntryOffset, EntrySize, Buffer); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "Can't flush partition table\n")); > + return NULL; > + } > + Buffer += EntrySize; > + return Buffer; > +} > + > +STATIC > +EFI_STATUS > +HiKeyFastbootPlatformFlashPartition ( > + IN CHAR8 *PartitionName, > + IN UINTN Size, > + IN VOID *Image > + ) > +{ > + EFI_STATUS Status; > + EFI_BLOCK_IO_PROTOCOL *BlockIo; > + EFI_DISK_IO_PROTOCOL *DiskIo; > + UINT32 MediaId; > + UINTN PartitionSize; > + FASTBOOT_PARTITION_LIST *Entry; > + CHAR16 PartitionNameUnicode[PARTITION_NAME_LENGTH]; > + BOOLEAN PartitionFound; > + VOID *Buffer; > + > + > + AsciiStrToUnicodeStr (PartitionName, PartitionNameUnicode); > + > + PartitionFound = FALSE; > + Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead)); > + while (!IsNull (&mPartitionListHead, &Entry->Link)) { > + // Search the partition list for the partition named by PartitionName > + if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) { > + PartitionFound = TRUE; > + break; > + } > + > + Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link); > + } > + if (!PartitionFound) { > + return EFI_NOT_FOUND; > + } > + > + Status = gBS->OpenProtocol ( > + Entry->PartitionHandle, > + &gEfiBlockIoProtocolGuid, > + (VOID **) &BlockIo, > + gImageHandle, > + NULL, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "Fastboot platform: couldn't open Block IO for flash: %r\n", Status)); > + return EFI_NOT_FOUND; > + } > + > + // Check image will fit on device > + // LastBlock counts from 0 > + PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize; > + if (PartitionSize < Size) { > + DEBUG ((DEBUG_ERROR, "Partition not big enough.\n")); > + DEBUG ((DEBUG_ERROR, "Partition Size:\t%ld\nImage Size:\t%ld\n", PartitionSize, Size)); > + > + return EFI_VOLUME_FULL; > + } > + > + MediaId = BlockIo->Media->MediaId; > + > + Status = gBS->OpenProtocol ( > + Entry->PartitionHandle, > + &gEfiDiskIoProtocolGuid, > + (VOID **) &DiskIo, > + gImageHandle, > + NULL, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + ASSERT_EFI_ERROR (Status); > + > + if (AsciiStrCmp (PartitionName, "ptable") == 0) { > + Buffer = WritePartition (Image, Size, DiskIo, BlockIo, "primary"); > + if (Buffer == NULL) { > + return EFI_DEVICE_ERROR; > + } > + if (Size >= (2 * PartitionSize)) { > + Buffer = WritePartition (Buffer, Size, DiskIo, BlockIo, "second"); > + if (Buffer == NULL) { > + return EFI_DEVICE_ERROR; > + } > + } Yes, this bit looks a lot better now. > + } else { > + Status = DiskIo->WriteDisk (DiskIo, MediaId, 0, Size, Image); > + } > + > + BlockIo->FlushBlocks(BlockIo); > + // wait DMA finished > + MicroSecondDelay (50000); > + > + return Status; > +} > + > +STATIC > +EFI_STATUS > +HiKeyFastbootPlatformErasePartition ( > + IN CHAR8 *PartitionName > + ) > +{ > + return EFI_SUCCESS; > +} > + > +STATIC > +EFI_STATUS > +HiKeyFastbootPlatformGetVar ( > + IN CHAR8 *Name, > + OUT CHAR8 *Value > + ) > +{ > + EFI_STATUS Status; > + EFI_BLOCK_IO_PROTOCOL *BlockIo; > + UINT64 PartitionSize; > + FASTBOOT_PARTITION_LIST *Entry; > + CHAR16 PartitionNameUnicode[PARTITION_NAME_LENGTH]; > + BOOLEAN PartitionFound; > + CHAR16 DataUnicode[SERIAL_NUMBER_LENGTH + 1]; // terminated '\0' > + UINTN VariableSize; > + CHAR8 PartTypeStr[] = "partition-type"; > + CHAR8 PartSizeStr[] = "partition-size"; > + > + if (!AsciiStrCmp (Name, "max-download-size")) { > + AsciiStrCpy (Value, FixedPcdGetPtr (PcdArmFastbootFlashLimit)); > + } else if (!AsciiStrCmp (Name, "product")) { > + AsciiStrCpy (Value, FixedPcdGetPtr (PcdFirmwareVendor)); > + } else if (!AsciiStrCmp (Name, "serialno")) { > + VariableSize = (SERIAL_NUMBER_LENGTH + 1) * sizeof (CHAR16); > + Status = gRT->GetVariable ( > + (CHAR16 *)L"SerialNo", > + &gHiKeyVariableGuid, > + NULL, > + &VariableSize, > + &DataUnicode > + ); > + if (EFI_ERROR (Status)) { > + *Value = '\0'; > + return EFI_NOT_FOUND; > + } > + DataUnicode[SERIAL_NUMBER_LENGTH * sizeof(CHAR16)] = '\0'; > + UnicodeStrToAsciiStr (DataUnicode, Value); > + } else if (!AsciiStrnCmp (Name, PartSizeStr, AsciiStrLen (PartSizeStr))) { > + // skip ':', then copy > + AsciiStrToUnicodeStr ((Name + AsciiStrLen (PartSizeStr) + 1), PartitionNameUnicode); > + PartitionFound = FALSE; > + Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead)); > + while (!IsNull (&mPartitionListHead, &Entry->Link)) { > + // Search the partition list for the partition named by PartitionName > + if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) { > + PartitionFound = TRUE; > + break; > + } > + > + Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link); > + } > + if (!PartitionFound) { > + *Value = '\0'; > + return EFI_NOT_FOUND; > + } > + > + Status = gBS->OpenProtocol ( > + Entry->PartitionHandle, > + &gEfiBlockIoProtocolGuid, > + (VOID **) &BlockIo, > + gImageHandle, > + NULL, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "Fastboot platform: couldn't open Block IO for flash: %r\n", Status)); > + *Value = '\0'; > + return EFI_NOT_FOUND; > + } > + > + // LastBlock counts from 0 > + PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize; > + DEBUG ((DEBUG_INFO, "Fastboot platform: check for partition-size:%a 0x%llx\n", Name, PartitionSize)); > + AsciiSPrint (Value, PARTITION_SIZE_LENGTH, "0x%llx", PartitionSize); > + } else if ( !AsciiStrnCmp (Name, PartTypeStr, AsciiStrLen (PartTypeStr))) { > + DEBUG ((DEBUG_INFO, "Fastboot platform: check for partition-type:%a\n", Name + AsciiStrLen (PartTypeStr))); > + // skip ':' > + if (!AsciiStrCmp ((Name + AsciiStrLen (PartTypeStr) + 1) , "system") || > + !AsciiStrCmp ((Name + AsciiStrLen (PartTypeStr) + 1) , "userdata") || > + !AsciiStrCmp ((Name + AsciiStrLen (PartTypeStr) + 1) , "cache")) { > + AsciiStrCpy (Value, "ext4"); > + } else { > + AsciiStrCpy (Value, "raw"); > + } > + } else { > + *Value = '\0'; > + } > + return EFI_SUCCESS; > +} > + > +STATIC > +EFI_STATUS > +HiKeyFastbootPlatformOemCommand ( > + IN CHAR8 *Command > + ) > +{ > + if (AsciiStrCmp (Command, "Demonstrate") == 0) { > + DEBUG ((DEBUG_ERROR, "ARM OEM Fastboot command 'Demonstrate' received.\n")); > + return EFI_SUCCESS; > + } else { > + DEBUG ((DEBUG_ERROR, > + "HiKey: Unrecognised Fastboot OEM command: %s\n", > + Command > + )); > + return EFI_NOT_FOUND; > + } > +} > + > +FASTBOOT_PLATFORM_PROTOCOL mPlatformProtocol = { > + HiKeyFastbootPlatformInit, > + HiKeyFastbootPlatformUnInit, > + HiKeyFastbootPlatformFlashPartition, > + HiKeyFastbootPlatformErasePartition, > + HiKeyFastbootPlatformGetVar, > + HiKeyFastbootPlatformOemCommand > +}; > + > +EFI_STATUS > +EFIAPI > +HiKeyFastbootPlatformEntryPoint ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + return gBS->InstallProtocolInterface ( > + &ImageHandle, > + &gAndroidFastbootPlatformProtocolGuid, > + EFI_NATIVE_INTERFACE, > + &mPlatformProtocol > + ); > +} > diff --git a/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf > new file mode 100644 > index 0000000..353c6c3 > --- /dev/null > +++ b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf > @@ -0,0 +1,61 @@ > +#/** @file > +# > +# Copyright (c) 2014, ARM Ltd. All rights reserved.<BR> > +# Copyright (c) 2015-2017, Linaro. All rights reserved. > +# > +# This program and the accompanying materials > +# are licensed and made available under the terms and conditions of the BSD License > +# which accompanies this distribution. The full text of the license may be found at > +# http://opensource.org/licenses/bsd-license.php > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +# > +# > +#**/ > + > +[Defines] > + INF_VERSION = 0x00010019 > + BASE_NAME = HiKeyFastbootDxe > + FILE_GUID = 8e335c38-c4e1-494e-8011-37a858d9763d > + MODULE_TYPE = UEFI_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = HiKeyFastbootPlatformEntryPoint > + > +[Sources.common] > + HiKeyFastbootDxe.c > + > +[LibraryClasses] > + BaseLib > + BaseMemoryLib > + DebugLib > + DevicePathLib > + MemoryAllocationLib > + PcdLib > + UefiBootServicesTableLib > + UefiRuntimeServicesTableLib > + UefiDriverEntryPoint > + TimerLib Comment unaddressed from v3: --- Please insert TimerLib alphabetically. --- > + > +[Protocols] > + gAndroidFastbootPlatformProtocolGuid > + gEfiBlockIoProtocolGuid > + gEfiDiskIoProtocolGuid > + gEfiSimpleTextOutProtocolGuid > + gEfiEraseBlockProtocolGuid Comment unaddressed from v3: --- Please sort alphabetically. --- > + > +[Packages] > + EmbeddedPkg/EmbeddedPkg.dec > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + ArmPlatformPkg/ArmPlatformPkg.dec > + ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec > + ArmPkg/ArmPkg.dec > + OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKey.dec Comment unaddressed from v3: --- Please sort alphabetically. --- > + > +[Guids] > + gHiKeyVariableGuid > + > +[Pcd] > + gArmPlatformTokenSpaceGuid.PcdFirmwareVendor > + gHiKeyTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath > + gHiKeyTokenSpaceGuid.PcdArmFastbootFlashLimit > diff --git a/Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h b/Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h > new file mode 100644 > index 0000000..56d5a0e > --- /dev/null > +++ b/Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h > @@ -0,0 +1,24 @@ > +/** @file > +* > +* Copyright (c) 2013-2014, ARM Limited. All rights reserved. > +* Copyright (c) 2015-2017, Linaro. All rights reserved. > +* > +* This program and the accompanying materials > +* are licensed and made available under the terms and conditions of the BSD License > +* which accompanies this distribution. The full text of the license may be found at > +* http://opensource.org/licenses/bsd-license.php > +* > +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +* > +**/ > + > +#ifndef __HIKEY_VARIABLE_H__ > +#define __HIKEY_VARIABLE_H__ > + > +#define HIKEY_VARIABLE_GUID \ > + { 0x66b8d063, 0x1daa, 0x4c60, { 0xb9, 0xf2, 0x55, 0x0d, 0x7e, 0xe1, 0x2f, 0x38 } } > + > +extern EFI_GUID gHiKeyVariableGuid; > + > +#endif /* __HIKEY_VARIABLE_H__ */ > -- > 2.7.4 >
On 2017/3/1 23:13, Leif Lindholm wrote: > On Wed, Feb 15, 2017 at 10:54:59PM +0800, Haojian Zhuang wrote: >> Support HiKey Fastboot driver for Fastboot App. >> > > I asked a few questions on v3, which I received no replies to. > Here I asked: > --- > Question: I notice this version deletes the SPARSE_HEADER support, > which was one of the main differences compared to VEXpress driver. > Is this something you plan to introduce in future? > --- It'll be appended in future. There are two reasons that I remove it from this patch set. 1. There's some issue to download latest system.img into HiKey. 2. SPARSE_HEADER should be common case. It's better to parse it in AndroidFastboot App instead. > >> Contributed-under: TianoCore Contribution Agreement 1.0 >> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org> >> --- >> Platforms/Hisilicon/HiKey/HiKey.dec | 1 + >> .../HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c | 672 +++++++++++++++++++++ >> .../HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf | 61 ++ >> .../Hisilicon/HiKey/Include/Guid/HiKeyVariable.h | 24 + >> 4 files changed, 758 insertions(+) >> create mode 100644 Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c >> create mode 100644 Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf >> create mode 100644 Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h >> >> diff --git a/Platforms/Hisilicon/HiKey/HiKey.dec b/Platforms/Hisilicon/HiKey/HiKey.dec >> index 537138e..17c6484 100644 >> --- a/Platforms/Hisilicon/HiKey/HiKey.dec >> +++ b/Platforms/Hisilicon/HiKey/HiKey.dec >> @@ -30,6 +30,7 @@ >> >> [Guids.common] >> gHiKeyTokenSpaceGuid = { 0x91148425, 0xcdd2, 0x4830, { 0x8b, 0xd0, 0xc6, 0x1c, 0x6d, 0xea, 0x36, 0x21 } } >> + gHiKeyVariableGuid = { 0x66b8d063, 0x1daa, 0x4c60, { 0xb9, 0xf2, 0x55, 0x0d, 0x7e, 0xe1, 0x2f, 0x38 } } >> >> [PcdsFixedAtBuild.common] >> gHiKeyTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath|L""|VOID*|0x00000001 >> diff --git a/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c >> new file mode 100644 >> index 0000000..2597f7a >> --- /dev/null >> +++ b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c >> @@ -0,0 +1,672 @@ >> +/** @file >> + >> + Copyright (c) 2014, ARM Ltd. All rights reserved.<BR> >> + Copyright (c) 2015-2017, Linaro. All rights reserved. >> + >> + This program and the accompanying materials >> + are licensed and made available under the terms and conditions of the BSD License >> + which accompanies this distribution. The full text of the license may be found at >> + http://opensource.org/licenses/bsd-license.php >> + >> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, >> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. >> + >> +**/ >> + >> +/* >> + Implementation of the Android Fastboot Platform protocol, to be used by the >> + Fastboot UEFI application, for Hisilicon HiKey platform. >> +*/ >> + >> +#include <Protocol/AndroidFastbootPlatform.h> >> +#include <Protocol/BlockIo.h> >> +#include <Protocol/DiskIo.h> >> +#include <Protocol/EraseBlock.h> >> +#include <Protocol/SimpleTextOut.h> >> + >> +#include <Library/BaseLib.h> >> +#include <Library/BaseMemoryLib.h> >> +#include <Library/DebugLib.h> >> +#include <Library/DevicePathLib.h> >> +#include <Library/MemoryAllocationLib.h> >> +#include <Library/UefiBootServicesTableLib.h> >> +#include <Library/UefiRuntimeServicesTableLib.h> >> +#include <Library/PrintLib.h> >> +#include <Library/TimerLib.h> >> + >> +#include <Guid/HiKeyVariable.h> >> + >> +#define FLASH_DEVICE_PATH_SIZE(DevPath) ( GetDevicePathSize (DevPath) - \ >> + sizeof (EFI_DEVICE_PATH_PROTOCOL)) >> + >> +#define PARTITION_NAME_MAX_LENGTH 72/2 >> + >> +#define IS_ALPHA(Char) (((Char) <= L'z' && (Char) >= L'a') || \ >> + ((Char) <= L'Z' && (Char) >= L'Z')) >> +#define IS_HEXCHAR(Char) (((Char) <= L'9' && (Char) >= L'0') || \ >> + IS_ALPHA(Char)) >> + >> +#define SERIAL_NUMBER_LENGTH 16 >> +#define BOOT_DEVICE_LENGTH 16 >> + >> +#define HIKEY_ERASE_SIZE (16 * 1024 * 1024) >> +#define HIKEY_ERASE_BLOCKS (HIKEY_ERASE_SIZE / EFI_PAGE_SIZE) >> +#define PARTITION_TYPE_STRING "partition-type" >> +#define PARTITION_SIZE_STRING "partition-size" >> +// length of a 12-byte hex string >> +#define PARTITION_SIZE_LENGTH 12 >> +#define PARTITION_NAME_LENGTH 36 // CHAR16 > > And here I asked: > --- > Where does this limit come from? Specification? > --- Yes, it's from GPT spec. > >> + >> +/* >> + * struct entry_head { >> + * unsigned char magic[8]; // "ENTRYHDR" >> + * unsigned char name[8]; // "primary"/"second" >> + * unsigned int start_lba; >> + * unsigned int count_lba; >> + * unsigned int flag; >> + * } >> + * >> + * ptable: >> + * ------------------------------------------------------ >> + * | head (primary) | content | head (second) | content | >> + * ------------------------------------------------------ >> + */ >> + >> +#define HIKEY_PTABLE_HEAD_MAGIC_LEN 8 >> +#define HIKEY_PTABLE_HEAD_NAME_LEN 8 >> +#define HIKEY_PTABLE_HEAD_SIZE 28 >> +#define HIKEY_PTABLE_CONTENT_OFFSET 512 >> + >> + >> +typedef struct _FASTBOOT_PARTITION_LIST { >> + LIST_ENTRY Link; >> + CHAR16 PartitionName[PARTITION_NAME_MAX_LENGTH]; >> + EFI_HANDLE PartitionHandle; >> + EFI_LBA Lba; >> +} FASTBOOT_PARTITION_LIST; >> + >> +STATIC LIST_ENTRY mPartitionListHead; >> + >> +/* >> + Helper to free the partition list >> +*/ >> +STATIC >> +VOID >> +FreePartitionList ( >> + VOID >> + ) >> +{ >> + FASTBOOT_PARTITION_LIST *Entry; >> + FASTBOOT_PARTITION_LIST *NextEntry; >> + >> + Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&mPartitionListHead); >> + while (!IsNull (&mPartitionListHead, &Entry->Link)) { >> + NextEntry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &Entry->Link); >> + >> + RemoveEntryList (&Entry->Link); >> + FreePool (Entry); >> + >> + Entry = NextEntry; >> + } >> +} >> +/* >> + Read the PartitionName fields from the GPT partition entries, putting them >> + into an allocated array that should later be freed. >> +*/ >> +STATIC >> +EFI_STATUS >> +ReadPartitionEntries ( >> + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, >> + OUT EFI_PARTITION_ENTRY **PartitionEntries >> + ) >> +{ >> + UINTN EntrySize; >> + UINTN NumEntries; >> + UINTN BufferSize; >> + UINT32 MediaId; >> + EFI_PARTITION_TABLE_HEADER *GptHeader; >> + EFI_STATUS Status; >> + >> + MediaId = BlockIo->Media->MediaId; >> + >> + // >> + // Read size of Partition entry and number of entries from GPT header >> + // >> + >> + GptHeader = AllocatePool (BlockIo->Media->BlockSize); >> + if (GptHeader == NULL) { >> + return EFI_OUT_OF_RESOURCES; >> + } >> + >> + Status = BlockIo->ReadBlocks (BlockIo, MediaId, 1, BlockIo->Media->BlockSize, GptHeader); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + // Check there is a GPT on the media >> + if (GptHeader->Header.Signature != EFI_PTAB_HEADER_ID || >> + GptHeader->MyLBA != 1) { >> + DEBUG ((DEBUG_ERROR, >> + "Fastboot platform: No GPT on flash. " >> + "Fastboot on HiKey does not support MBR.\n" >> + )); >> + return EFI_DEVICE_ERROR; >> + } >> + >> + EntrySize = GptHeader->SizeOfPartitionEntry; >> + NumEntries = GptHeader->NumberOfPartitionEntries; >> + >> + FreePool (GptHeader); >> + >> + ASSERT (EntrySize != 0); >> + ASSERT (NumEntries != 0); >> + >> + BufferSize = ALIGN_VALUE (EntrySize * NumEntries, BlockIo->Media->BlockSize); >> + *PartitionEntries = AllocatePool (BufferSize); >> + if (PartitionEntries == NULL) { >> + return EFI_OUT_OF_RESOURCES; >> + } >> + >> + Status = BlockIo->ReadBlocks (BlockIo, MediaId, 2, BufferSize, (VOID *) *PartitionEntries); >> + if (EFI_ERROR (Status)) { >> + FreePool (PartitionEntries); >> + return Status; >> + } >> + >> + return Status; >> +} >> + >> + >> +STATIC >> +EFI_STATUS >> +CreateGptPartitionEntry ( >> + IN EFI_HANDLE *AllHandles, >> + IN UINTN LoopIndex, >> + IN HARDDRIVE_DEVICE_PATH *PartitionNode, >> + IN EFI_PARTITION_ENTRY *PartitionEntries >> + ) >> +{ >> + FASTBOOT_PARTITION_LIST *Entry; >> + >> + // Create entry >> + Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST)); >> + if (Entry == NULL) { >> + return EFI_OUT_OF_RESOURCES; >> + } >> + >> + // 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 >> + ); >> + Entry->Lba = PartitionEntries[PartitionNode->PartitionNumber - 1].StartingLBA; >> + 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 ((DEBUG_WARN, >> + "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 >> + )); >> + } >> + return EFI_SUCCESS; >> +} >> + >> +STATIC >> +EFI_STATUS >> +CreatePartitionEntry ( >> + IN EFI_HANDLE *AllHandles, >> + IN UINTN LoopIndex, >> + IN EFI_DEVICE_PATH_PROTOCOL *FlashDevicePath, >> + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, >> + IN EFI_PARTITION_ENTRY *PartitionEntries >> + ) >> +{ >> + EFI_DEVICE_PATH_PROTOCOL *NextNode; >> + FASTBOOT_PARTITION_LIST *Entry; >> + HARDDRIVE_DEVICE_PATH *PartitionNode; >> + >> + // Fill out if it isn't a sub-device of the flash device >> + if (CompareMem (DevicePath, FlashDevicePath, FLASH_DEVICE_PATH_SIZE (FlashDevicePath))) { >> + return EFI_SUCCESS; >> + } >> + // Device path starts with path of flash device. Check it isn't the flash >> + // device itself. >> + NextNode = NextDevicePathNode (DevicePath); >> + if (IsDevicePathEndType (NextNode)) { >> + // Create entry >> + Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST)); >> + if (Entry == NULL) { >> + return EFI_OUT_OF_RESOURCES; >> + } >> + >> + // Copy handle and partition name >> + Entry->PartitionHandle = AllHandles[LoopIndex]; >> + StrCpy (Entry->PartitionName, L"ptable"); >> + InsertTailList (&mPartitionListHead, &Entry->Link); >> + return EFI_SUCCESS; >> + } >> + >> + // 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) { >> + return EFI_SUCCESS; >> + } >> + return CreateGptPartitionEntry (AllHandles, LoopIndex, PartitionNode, PartitionEntries); >> +} >> + >> +/* >> + 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 >> + HiKeyFastbootPlatformFlashPartition. >> +*/ >> +STATIC >> +EFI_STATUS >> +HiKeyFastbootPlatformInit ( >> + VOID >> + ) >> +{ >> + EFI_STATUS Status; >> + EFI_DEVICE_PATH_PROTOCOL *FlashDevicePath; >> + EFI_DEVICE_PATH_PROTOCOL *FlashDevicePathDup; >> + EFI_DEVICE_PATH_PROTOCOL *DevicePath; >> + UINTN NumHandles; >> + EFI_HANDLE *AllHandles; >> + UINTN LoopIndex; >> + EFI_HANDLE FlashHandle; >> + EFI_BLOCK_IO_PROTOCOL *FlashBlockIo; >> + EFI_PARTITION_ENTRY *PartitionEntries; >> + >> + 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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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); >> + >> + Status = CreatePartitionEntry ( >> + AllHandles, >> + LoopIndex, >> + FlashDevicePath, >> + DevicePath, >> + PartitionEntries >> + ); >> + if (EFI_ERROR (Status)) { >> + FreePartitionList (); >> + goto Exit; >> + } >> + } >> + >> +Exit: >> + FreePool (PartitionEntries); >> + FreePool (FlashDevicePath); >> + FreePool (AllHandles); >> + return Status; >> + >> +} >> + >> +STATIC >> +VOID >> +HiKeyFastbootPlatformUnInit ( >> + VOID >> + ) >> +{ >> + FreePartitionList (); >> +} >> + >> +STATIC >> +VOID * >> +WritePartition ( >> + IN VOID *Image, >> + IN UINTN Size, >> + IN EFI_DISK_IO_PROTOCOL *DiskIo, >> + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, >> + IN CHAR8 *Name >> + ) >> +{ >> + UINT32 EntrySize, EntryOffset; >> + EFI_STATUS Status; >> + VOID *Buffer; >> + >> + Buffer = Image; >> + // not a string with terminated '\0' >> + if (AsciiStrnCmp (Buffer, "ENTRYHDR", HIKEY_PTABLE_HEAD_MAGIC_LEN) != 0) { >> + DEBUG ((DEBUG_ERROR, "unknown ptable image\n")); >> + return NULL; >> + } >> + Buffer += HIKEY_PTABLE_HEAD_MAGIC_LEN; >> + // not a string with terminated '\0' >> + if (AsciiStrnCmp (Buffer, Name, HIKEY_PTABLE_HEAD_NAME_LEN) != 0) { >> + DEBUG ((DEBUG_ERROR, "unknown ptable image\n")); >> + return NULL; >> + } >> + Buffer += HIKEY_PTABLE_HEAD_NAME_LEN; >> + EntryOffset = *(UINT32 *)Buffer * BlockIo->Media->BlockSize; >> + Buffer += sizeof (UINT32); >> + EntrySize = *(UINT32 *)Buffer * BlockIo->Media->BlockSize; >> + if ((EntrySize + HIKEY_PTABLE_CONTENT_OFFSET) > Size) { >> + DEBUG ((DEBUG_ERROR, "Entry size doesn't match\n")); >> + return NULL; >> + } >> + Buffer = Image + HIKEY_PTABLE_CONTENT_OFFSET; >> + Status = DiskIo->WriteDisk (DiskIo, BlockIo->Media->MediaId, EntryOffset, EntrySize, Buffer); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "Can't flush partition table\n")); >> + return NULL; >> + } >> + Buffer += EntrySize; >> + return Buffer; >> +} >> + >> +STATIC >> +EFI_STATUS >> +HiKeyFastbootPlatformFlashPartition ( >> + IN CHAR8 *PartitionName, >> + IN UINTN Size, >> + IN VOID *Image >> + ) >> +{ >> + EFI_STATUS Status; >> + EFI_BLOCK_IO_PROTOCOL *BlockIo; >> + EFI_DISK_IO_PROTOCOL *DiskIo; >> + UINT32 MediaId; >> + UINTN PartitionSize; >> + FASTBOOT_PARTITION_LIST *Entry; >> + CHAR16 PartitionNameUnicode[PARTITION_NAME_LENGTH]; >> + BOOLEAN PartitionFound; >> + VOID *Buffer; >> + >> + >> + AsciiStrToUnicodeStr (PartitionName, PartitionNameUnicode); >> + >> + PartitionFound = FALSE; >> + Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead)); >> + while (!IsNull (&mPartitionListHead, &Entry->Link)) { >> + // Search the partition list for the partition named by PartitionName >> + if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) { >> + PartitionFound = TRUE; >> + break; >> + } >> + >> + Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link); >> + } >> + if (!PartitionFound) { >> + return EFI_NOT_FOUND; >> + } >> + >> + Status = gBS->OpenProtocol ( >> + Entry->PartitionHandle, >> + &gEfiBlockIoProtocolGuid, >> + (VOID **) &BlockIo, >> + gImageHandle, >> + NULL, >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "Fastboot platform: couldn't open Block IO for flash: %r\n", Status)); >> + return EFI_NOT_FOUND; >> + } >> + >> + // Check image will fit on device >> + // LastBlock counts from 0 >> + PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize; >> + if (PartitionSize < Size) { >> + DEBUG ((DEBUG_ERROR, "Partition not big enough.\n")); >> + DEBUG ((DEBUG_ERROR, "Partition Size:\t%ld\nImage Size:\t%ld\n", PartitionSize, Size)); >> + >> + return EFI_VOLUME_FULL; >> + } >> + >> + MediaId = BlockIo->Media->MediaId; >> + >> + Status = gBS->OpenProtocol ( >> + Entry->PartitionHandle, >> + &gEfiDiskIoProtocolGuid, >> + (VOID **) &DiskIo, >> + gImageHandle, >> + NULL, >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> + ); >> + ASSERT_EFI_ERROR (Status); >> + >> + if (AsciiStrCmp (PartitionName, "ptable") == 0) { >> + Buffer = WritePartition (Image, Size, DiskIo, BlockIo, "primary"); >> + if (Buffer == NULL) { >> + return EFI_DEVICE_ERROR; >> + } >> + if (Size >= (2 * PartitionSize)) { >> + Buffer = WritePartition (Buffer, Size, DiskIo, BlockIo, "second"); >> + if (Buffer == NULL) { >> + return EFI_DEVICE_ERROR; >> + } >> + } > > Yes, this bit looks a lot better now. > >> + } else { >> + Status = DiskIo->WriteDisk (DiskIo, MediaId, 0, Size, Image); >> + } >> + >> + BlockIo->FlushBlocks(BlockIo); >> + // wait DMA finished >> + MicroSecondDelay (50000); >> + >> + return Status; >> +} >> + >> +STATIC >> +EFI_STATUS >> +HiKeyFastbootPlatformErasePartition ( >> + IN CHAR8 *PartitionName >> + ) >> +{ >> + return EFI_SUCCESS; >> +} >> + >> +STATIC >> +EFI_STATUS >> +HiKeyFastbootPlatformGetVar ( >> + IN CHAR8 *Name, >> + OUT CHAR8 *Value >> + ) >> +{ >> + EFI_STATUS Status; >> + EFI_BLOCK_IO_PROTOCOL *BlockIo; >> + UINT64 PartitionSize; >> + FASTBOOT_PARTITION_LIST *Entry; >> + CHAR16 PartitionNameUnicode[PARTITION_NAME_LENGTH]; >> + BOOLEAN PartitionFound; >> + CHAR16 DataUnicode[SERIAL_NUMBER_LENGTH + 1]; // terminated '\0' >> + UINTN VariableSize; >> + CHAR8 PartTypeStr[] = "partition-type"; >> + CHAR8 PartSizeStr[] = "partition-size"; >> + >> + if (!AsciiStrCmp (Name, "max-download-size")) { >> + AsciiStrCpy (Value, FixedPcdGetPtr (PcdArmFastbootFlashLimit)); >> + } else if (!AsciiStrCmp (Name, "product")) { >> + AsciiStrCpy (Value, FixedPcdGetPtr (PcdFirmwareVendor)); >> + } else if (!AsciiStrCmp (Name, "serialno")) { >> + VariableSize = (SERIAL_NUMBER_LENGTH + 1) * sizeof (CHAR16); >> + Status = gRT->GetVariable ( >> + (CHAR16 *)L"SerialNo", >> + &gHiKeyVariableGuid, >> + NULL, >> + &VariableSize, >> + &DataUnicode >> + ); >> + if (EFI_ERROR (Status)) { >> + *Value = '\0'; >> + return EFI_NOT_FOUND; >> + } >> + DataUnicode[SERIAL_NUMBER_LENGTH * sizeof(CHAR16)] = '\0'; >> + UnicodeStrToAsciiStr (DataUnicode, Value); >> + } else if (!AsciiStrnCmp (Name, PartSizeStr, AsciiStrLen (PartSizeStr))) { >> + // skip ':', then copy >> + AsciiStrToUnicodeStr ((Name + AsciiStrLen (PartSizeStr) + 1), PartitionNameUnicode); >> + PartitionFound = FALSE; >> + Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead)); >> + while (!IsNull (&mPartitionListHead, &Entry->Link)) { >> + // Search the partition list for the partition named by PartitionName >> + if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) { >> + PartitionFound = TRUE; >> + break; >> + } >> + >> + Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link); >> + } >> + if (!PartitionFound) { >> + *Value = '\0'; >> + return EFI_NOT_FOUND; >> + } >> + >> + Status = gBS->OpenProtocol ( >> + Entry->PartitionHandle, >> + &gEfiBlockIoProtocolGuid, >> + (VOID **) &BlockIo, >> + gImageHandle, >> + NULL, >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "Fastboot platform: couldn't open Block IO for flash: %r\n", Status)); >> + *Value = '\0'; >> + return EFI_NOT_FOUND; >> + } >> + >> + // LastBlock counts from 0 >> + PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize; >> + DEBUG ((DEBUG_INFO, "Fastboot platform: check for partition-size:%a 0x%llx\n", Name, PartitionSize)); >> + AsciiSPrint (Value, PARTITION_SIZE_LENGTH, "0x%llx", PartitionSize); >> + } else if ( !AsciiStrnCmp (Name, PartTypeStr, AsciiStrLen (PartTypeStr))) { >> + DEBUG ((DEBUG_INFO, "Fastboot platform: check for partition-type:%a\n", Name + AsciiStrLen (PartTypeStr))); >> + // skip ':' >> + if (!AsciiStrCmp ((Name + AsciiStrLen (PartTypeStr) + 1) , "system") || >> + !AsciiStrCmp ((Name + AsciiStrLen (PartTypeStr) + 1) , "userdata") || >> + !AsciiStrCmp ((Name + AsciiStrLen (PartTypeStr) + 1) , "cache")) { >> + AsciiStrCpy (Value, "ext4"); >> + } else { >> + AsciiStrCpy (Value, "raw"); >> + } >> + } else { >> + *Value = '\0'; >> + } >> + return EFI_SUCCESS; >> +} >> + >> +STATIC >> +EFI_STATUS >> +HiKeyFastbootPlatformOemCommand ( >> + IN CHAR8 *Command >> + ) >> +{ >> + if (AsciiStrCmp (Command, "Demonstrate") == 0) { >> + DEBUG ((DEBUG_ERROR, "ARM OEM Fastboot command 'Demonstrate' received.\n")); >> + return EFI_SUCCESS; >> + } else { >> + DEBUG ((DEBUG_ERROR, >> + "HiKey: Unrecognised Fastboot OEM command: %s\n", >> + Command >> + )); >> + return EFI_NOT_FOUND; >> + } >> +} >> + >> +FASTBOOT_PLATFORM_PROTOCOL mPlatformProtocol = { >> + HiKeyFastbootPlatformInit, >> + HiKeyFastbootPlatformUnInit, >> + HiKeyFastbootPlatformFlashPartition, >> + HiKeyFastbootPlatformErasePartition, >> + HiKeyFastbootPlatformGetVar, >> + HiKeyFastbootPlatformOemCommand >> +}; >> + >> +EFI_STATUS >> +EFIAPI >> +HiKeyFastbootPlatformEntryPoint ( >> + IN EFI_HANDLE ImageHandle, >> + IN EFI_SYSTEM_TABLE *SystemTable >> + ) >> +{ >> + return gBS->InstallProtocolInterface ( >> + &ImageHandle, >> + &gAndroidFastbootPlatformProtocolGuid, >> + EFI_NATIVE_INTERFACE, >> + &mPlatformProtocol >> + ); >> +} >> diff --git a/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf >> new file mode 100644 >> index 0000000..353c6c3 >> --- /dev/null >> +++ b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf >> @@ -0,0 +1,61 @@ >> +#/** @file >> +# >> +# Copyright (c) 2014, ARM Ltd. All rights reserved.<BR> >> +# Copyright (c) 2015-2017, Linaro. All rights reserved. >> +# >> +# This program and the accompanying materials >> +# are licensed and made available under the terms and conditions of the BSD License >> +# which accompanies this distribution. The full text of the license may be found at >> +# http://opensource.org/licenses/bsd-license.php >> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, >> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. >> +# >> +# >> +#**/ >> + >> +[Defines] >> + INF_VERSION = 0x00010019 >> + BASE_NAME = HiKeyFastbootDxe >> + FILE_GUID = 8e335c38-c4e1-494e-8011-37a858d9763d >> + MODULE_TYPE = UEFI_DRIVER >> + VERSION_STRING = 1.0 >> + ENTRY_POINT = HiKeyFastbootPlatformEntryPoint >> + >> +[Sources.common] >> + HiKeyFastbootDxe.c >> + >> +[LibraryClasses] >> + BaseLib >> + BaseMemoryLib >> + DebugLib >> + DevicePathLib >> + MemoryAllocationLib >> + PcdLib >> + UefiBootServicesTableLib >> + UefiRuntimeServicesTableLib >> + UefiDriverEntryPoint >> + TimerLib > > Comment unaddressed from v3: > --- > Please insert TimerLib alphabetically. > --- OK > >> + >> +[Protocols] >> + gAndroidFastbootPlatformProtocolGuid >> + gEfiBlockIoProtocolGuid >> + gEfiDiskIoProtocolGuid >> + gEfiSimpleTextOutProtocolGuid >> + gEfiEraseBlockProtocolGuid > > Comment unaddressed from v3: > --- > Please sort alphabetically. > --- OK > >> + >> +[Packages] >> + EmbeddedPkg/EmbeddedPkg.dec >> + MdePkg/MdePkg.dec >> + MdeModulePkg/MdeModulePkg.dec >> + ArmPlatformPkg/ArmPlatformPkg.dec >> + ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec >> + ArmPkg/ArmPkg.dec >> + OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKey.dec > > Comment unaddressed from v3: > --- > Please sort alphabetically. > --- > >> + >> +[Guids] >> + gHiKeyVariableGuid >> + >> +[Pcd] >> + gArmPlatformTokenSpaceGuid.PcdFirmwareVendor >> + gHiKeyTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath >> + gHiKeyTokenSpaceGuid.PcdArmFastbootFlashLimit >> diff --git a/Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h b/Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h >> new file mode 100644 >> index 0000000..56d5a0e >> --- /dev/null >> +++ b/Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h >> @@ -0,0 +1,24 @@ >> +/** @file >> +* >> +* Copyright (c) 2013-2014, ARM Limited. All rights reserved. >> +* Copyright (c) 2015-2017, Linaro. All rights reserved. >> +* >> +* This program and the accompanying materials >> +* are licensed and made available under the terms and conditions of the BSD License >> +* which accompanies this distribution. The full text of the license may be found at >> +* http://opensource.org/licenses/bsd-license.php >> +* >> +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, >> +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. >> +* >> +**/ >> + >> +#ifndef __HIKEY_VARIABLE_H__ >> +#define __HIKEY_VARIABLE_H__ >> + >> +#define HIKEY_VARIABLE_GUID \ >> + { 0x66b8d063, 0x1daa, 0x4c60, { 0xb9, 0xf2, 0x55, 0x0d, 0x7e, 0xe1, 0x2f, 0x38 } } >> + >> +extern EFI_GUID gHiKeyVariableGuid; >> + >> +#endif /* __HIKEY_VARIABLE_H__ */ >> -- >> 2.7.4 >>
On Thu, Mar 02, 2017 at 09:32:29AM +0800, Haojian Zhuang wrote: > On 2017/3/1 23:13, Leif Lindholm wrote: > >On Wed, Feb 15, 2017 at 10:54:59PM +0800, Haojian Zhuang wrote: > >>Support HiKey Fastboot driver for Fastboot App. > >> > > > >I asked a few questions on v3, which I received no replies to. > >Here I asked: > >--- > >Question: I notice this version deletes the SPARSE_HEADER support, > >which was one of the main differences compared to VEXpress driver. > >Is this something you plan to introduce in future? > >--- > > It'll be appended in future. There are two reasons that I remove it > from this patch set. > 1. There's some issue to download latest system.img into HiKey. > 2. SPARSE_HEADER should be common case. It's better to parse it in > AndroidFastboot App instead. OK. I would be quite keen to look into merging these versions back together in the future, but it's fine for now. > > > >>Contributed-under: TianoCore Contribution Agreement 1.0 > >>Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org> > >>--- > >> Platforms/Hisilicon/HiKey/HiKey.dec | 1 + > >> .../HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c | 672 +++++++++++++++++++++ > >> .../HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf | 61 ++ > >> .../Hisilicon/HiKey/Include/Guid/HiKeyVariable.h | 24 + > >> 4 files changed, 758 insertions(+) > >> create mode 100644 Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c > >> create mode 100644 Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf > >> create mode 100644 Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h > >> > >>diff --git a/Platforms/Hisilicon/HiKey/HiKey.dec b/Platforms/Hisilicon/HiKey/HiKey.dec > >>index 537138e..17c6484 100644 > >>--- a/Platforms/Hisilicon/HiKey/HiKey.dec > >>+++ b/Platforms/Hisilicon/HiKey/HiKey.dec > >>@@ -30,6 +30,7 @@ > >> > >> [Guids.common] > >> gHiKeyTokenSpaceGuid = { 0x91148425, 0xcdd2, 0x4830, { 0x8b, 0xd0, 0xc6, 0x1c, 0x6d, 0xea, 0x36, 0x21 } } > >>+ gHiKeyVariableGuid = { 0x66b8d063, 0x1daa, 0x4c60, { 0xb9, 0xf2, 0x55, 0x0d, 0x7e, 0xe1, 0x2f, 0x38 } } > >> > >> [PcdsFixedAtBuild.common] > >> gHiKeyTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath|L""|VOID*|0x00000001 > >>diff --git a/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c > >>new file mode 100644 > >>index 0000000..2597f7a > >>--- /dev/null > >>+++ b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c > >>@@ -0,0 +1,672 @@ > >>+/** @file > >>+ > >>+ Copyright (c) 2014, ARM Ltd. All rights reserved.<BR> > >>+ Copyright (c) 2015-2017, Linaro. All rights reserved. > >>+ > >>+ This program and the accompanying materials > >>+ are licensed and made available under the terms and conditions of the BSD License > >>+ which accompanies this distribution. The full text of the license may be found at > >>+ http://opensource.org/licenses/bsd-license.php > >>+ > >>+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > >>+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > >>+ > >>+**/ > >>+ > >>+/* > >>+ Implementation of the Android Fastboot Platform protocol, to be used by the > >>+ Fastboot UEFI application, for Hisilicon HiKey platform. > >>+*/ > >>+ > >>+#include <Protocol/AndroidFastbootPlatform.h> > >>+#include <Protocol/BlockIo.h> > >>+#include <Protocol/DiskIo.h> > >>+#include <Protocol/EraseBlock.h> > >>+#include <Protocol/SimpleTextOut.h> > >>+ > >>+#include <Library/BaseLib.h> > >>+#include <Library/BaseMemoryLib.h> > >>+#include <Library/DebugLib.h> > >>+#include <Library/DevicePathLib.h> > >>+#include <Library/MemoryAllocationLib.h> > >>+#include <Library/UefiBootServicesTableLib.h> > >>+#include <Library/UefiRuntimeServicesTableLib.h> > >>+#include <Library/PrintLib.h> > >>+#include <Library/TimerLib.h> > >>+ > >>+#include <Guid/HiKeyVariable.h> > >>+ > >>+#define FLASH_DEVICE_PATH_SIZE(DevPath) ( GetDevicePathSize (DevPath) - \ > >>+ sizeof (EFI_DEVICE_PATH_PROTOCOL)) > >>+ > >>+#define PARTITION_NAME_MAX_LENGTH 72/2 > >>+ > >>+#define IS_ALPHA(Char) (((Char) <= L'z' && (Char) >= L'a') || \ > >>+ ((Char) <= L'Z' && (Char) >= L'Z')) > >>+#define IS_HEXCHAR(Char) (((Char) <= L'9' && (Char) >= L'0') || \ > >>+ IS_ALPHA(Char)) > >>+ > >>+#define SERIAL_NUMBER_LENGTH 16 > >>+#define BOOT_DEVICE_LENGTH 16 > >>+ > >>+#define HIKEY_ERASE_SIZE (16 * 1024 * 1024) > >>+#define HIKEY_ERASE_BLOCKS (HIKEY_ERASE_SIZE / EFI_PAGE_SIZE) > >>+#define PARTITION_TYPE_STRING "partition-type" > >>+#define PARTITION_SIZE_STRING "partition-size" > >>+// length of a 12-byte hex string > >>+#define PARTITION_SIZE_LENGTH 12 > >>+#define PARTITION_NAME_LENGTH 36 // CHAR16 > > > >And here I asked: > >--- > >Where does this limit come from? Specification? > >--- > > Yes, it's from GPT spec. OK - can you do one of: - add a comment to that effect to any definition imported from the spec - or just group all of these together under a single comment - rename definitions based on the GPT specification, adding GPT_ prefix ? / Leif
diff --git a/Platforms/Hisilicon/HiKey/HiKey.dec b/Platforms/Hisilicon/HiKey/HiKey.dec index 537138e..17c6484 100644 --- a/Platforms/Hisilicon/HiKey/HiKey.dec +++ b/Platforms/Hisilicon/HiKey/HiKey.dec @@ -30,6 +30,7 @@ [Guids.common] gHiKeyTokenSpaceGuid = { 0x91148425, 0xcdd2, 0x4830, { 0x8b, 0xd0, 0xc6, 0x1c, 0x6d, 0xea, 0x36, 0x21 } } + gHiKeyVariableGuid = { 0x66b8d063, 0x1daa, 0x4c60, { 0xb9, 0xf2, 0x55, 0x0d, 0x7e, 0xe1, 0x2f, 0x38 } } [PcdsFixedAtBuild.common] gHiKeyTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath|L""|VOID*|0x00000001 diff --git a/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c new file mode 100644 index 0000000..2597f7a --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c @@ -0,0 +1,672 @@ +/** @file + + Copyright (c) 2014, ARM Ltd. All rights reserved.<BR> + Copyright (c) 2015-2017, Linaro. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/* + Implementation of the Android Fastboot Platform protocol, to be used by the + Fastboot UEFI application, for Hisilicon HiKey platform. +*/ + +#include <Protocol/AndroidFastbootPlatform.h> +#include <Protocol/BlockIo.h> +#include <Protocol/DiskIo.h> +#include <Protocol/EraseBlock.h> +#include <Protocol/SimpleTextOut.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/DevicePathLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/PrintLib.h> +#include <Library/TimerLib.h> + +#include <Guid/HiKeyVariable.h> + +#define FLASH_DEVICE_PATH_SIZE(DevPath) ( GetDevicePathSize (DevPath) - \ + sizeof (EFI_DEVICE_PATH_PROTOCOL)) + +#define PARTITION_NAME_MAX_LENGTH 72/2 + +#define IS_ALPHA(Char) (((Char) <= L'z' && (Char) >= L'a') || \ + ((Char) <= L'Z' && (Char) >= L'Z')) +#define IS_HEXCHAR(Char) (((Char) <= L'9' && (Char) >= L'0') || \ + IS_ALPHA(Char)) + +#define SERIAL_NUMBER_LENGTH 16 +#define BOOT_DEVICE_LENGTH 16 + +#define HIKEY_ERASE_SIZE (16 * 1024 * 1024) +#define HIKEY_ERASE_BLOCKS (HIKEY_ERASE_SIZE / EFI_PAGE_SIZE) +#define PARTITION_TYPE_STRING "partition-type" +#define PARTITION_SIZE_STRING "partition-size" +// length of a 12-byte hex string +#define PARTITION_SIZE_LENGTH 12 +#define PARTITION_NAME_LENGTH 36 // CHAR16 + +/* + * struct entry_head { + * unsigned char magic[8]; // "ENTRYHDR" + * unsigned char name[8]; // "primary"/"second" + * unsigned int start_lba; + * unsigned int count_lba; + * unsigned int flag; + * } + * + * ptable: + * ------------------------------------------------------ + * | head (primary) | content | head (second) | content | + * ------------------------------------------------------ + */ + +#define HIKEY_PTABLE_HEAD_MAGIC_LEN 8 +#define HIKEY_PTABLE_HEAD_NAME_LEN 8 +#define HIKEY_PTABLE_HEAD_SIZE 28 +#define HIKEY_PTABLE_CONTENT_OFFSET 512 + + +typedef struct _FASTBOOT_PARTITION_LIST { + LIST_ENTRY Link; + CHAR16 PartitionName[PARTITION_NAME_MAX_LENGTH]; + EFI_HANDLE PartitionHandle; + EFI_LBA Lba; +} FASTBOOT_PARTITION_LIST; + +STATIC LIST_ENTRY mPartitionListHead; + +/* + Helper to free the partition list +*/ +STATIC +VOID +FreePartitionList ( + VOID + ) +{ + FASTBOOT_PARTITION_LIST *Entry; + FASTBOOT_PARTITION_LIST *NextEntry; + + Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&mPartitionListHead); + while (!IsNull (&mPartitionListHead, &Entry->Link)) { + NextEntry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &Entry->Link); + + RemoveEntryList (&Entry->Link); + FreePool (Entry); + + Entry = NextEntry; + } +} +/* + Read the PartitionName fields from the GPT partition entries, putting them + into an allocated array that should later be freed. +*/ +STATIC +EFI_STATUS +ReadPartitionEntries ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + OUT EFI_PARTITION_ENTRY **PartitionEntries + ) +{ + UINTN EntrySize; + UINTN NumEntries; + UINTN BufferSize; + UINT32 MediaId; + EFI_PARTITION_TABLE_HEADER *GptHeader; + EFI_STATUS Status; + + MediaId = BlockIo->Media->MediaId; + + // + // Read size of Partition entry and number of entries from GPT header + // + + GptHeader = AllocatePool (BlockIo->Media->BlockSize); + if (GptHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = BlockIo->ReadBlocks (BlockIo, MediaId, 1, BlockIo->Media->BlockSize, GptHeader); + if (EFI_ERROR (Status)) { + return Status; + } + + // Check there is a GPT on the media + if (GptHeader->Header.Signature != EFI_PTAB_HEADER_ID || + GptHeader->MyLBA != 1) { + DEBUG ((DEBUG_ERROR, + "Fastboot platform: No GPT on flash. " + "Fastboot on HiKey does not support MBR.\n" + )); + return EFI_DEVICE_ERROR; + } + + EntrySize = GptHeader->SizeOfPartitionEntry; + NumEntries = GptHeader->NumberOfPartitionEntries; + + FreePool (GptHeader); + + ASSERT (EntrySize != 0); + ASSERT (NumEntries != 0); + + BufferSize = ALIGN_VALUE (EntrySize * NumEntries, BlockIo->Media->BlockSize); + *PartitionEntries = AllocatePool (BufferSize); + if (PartitionEntries == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = BlockIo->ReadBlocks (BlockIo, MediaId, 2, BufferSize, (VOID *) *PartitionEntries); + if (EFI_ERROR (Status)) { + FreePool (PartitionEntries); + return Status; + } + + return Status; +} + + +STATIC +EFI_STATUS +CreateGptPartitionEntry ( + IN EFI_HANDLE *AllHandles, + IN UINTN LoopIndex, + IN HARDDRIVE_DEVICE_PATH *PartitionNode, + IN EFI_PARTITION_ENTRY *PartitionEntries + ) +{ + FASTBOOT_PARTITION_LIST *Entry; + + // Create entry + Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST)); + if (Entry == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // 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 + ); + Entry->Lba = PartitionEntries[PartitionNode->PartitionNumber - 1].StartingLBA; + 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 ((DEBUG_WARN, + "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 + )); + } + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +CreatePartitionEntry ( + IN EFI_HANDLE *AllHandles, + IN UINTN LoopIndex, + IN EFI_DEVICE_PATH_PROTOCOL *FlashDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_PARTITION_ENTRY *PartitionEntries + ) +{ + EFI_DEVICE_PATH_PROTOCOL *NextNode; + FASTBOOT_PARTITION_LIST *Entry; + HARDDRIVE_DEVICE_PATH *PartitionNode; + + // Fill out if it isn't a sub-device of the flash device + if (CompareMem (DevicePath, FlashDevicePath, FLASH_DEVICE_PATH_SIZE (FlashDevicePath))) { + return EFI_SUCCESS; + } + // Device path starts with path of flash device. Check it isn't the flash + // device itself. + NextNode = NextDevicePathNode (DevicePath); + if (IsDevicePathEndType (NextNode)) { + // Create entry + Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST)); + if (Entry == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // Copy handle and partition name + Entry->PartitionHandle = AllHandles[LoopIndex]; + StrCpy (Entry->PartitionName, L"ptable"); + InsertTailList (&mPartitionListHead, &Entry->Link); + return EFI_SUCCESS; + } + + // 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) { + return EFI_SUCCESS; + } + return CreateGptPartitionEntry (AllHandles, LoopIndex, PartitionNode, PartitionEntries); +} + +/* + 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 + HiKeyFastbootPlatformFlashPartition. +*/ +STATIC +EFI_STATUS +HiKeyFastbootPlatformInit ( + VOID + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *FlashDevicePath; + EFI_DEVICE_PATH_PROTOCOL *FlashDevicePathDup; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN NumHandles; + EFI_HANDLE *AllHandles; + UINTN LoopIndex; + EFI_HANDLE FlashHandle; + EFI_BLOCK_IO_PROTOCOL *FlashBlockIo; + EFI_PARTITION_ENTRY *PartitionEntries; + + 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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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); + + Status = CreatePartitionEntry ( + AllHandles, + LoopIndex, + FlashDevicePath, + DevicePath, + PartitionEntries + ); + if (EFI_ERROR (Status)) { + FreePartitionList (); + goto Exit; + } + } + +Exit: + FreePool (PartitionEntries); + FreePool (FlashDevicePath); + FreePool (AllHandles); + return Status; + +} + +STATIC +VOID +HiKeyFastbootPlatformUnInit ( + VOID + ) +{ + FreePartitionList (); +} + +STATIC +VOID * +WritePartition ( + IN VOID *Image, + IN UINTN Size, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN CHAR8 *Name + ) +{ + UINT32 EntrySize, EntryOffset; + EFI_STATUS Status; + VOID *Buffer; + + Buffer = Image; + // not a string with terminated '\0' + if (AsciiStrnCmp (Buffer, "ENTRYHDR", HIKEY_PTABLE_HEAD_MAGIC_LEN) != 0) { + DEBUG ((DEBUG_ERROR, "unknown ptable image\n")); + return NULL; + } + Buffer += HIKEY_PTABLE_HEAD_MAGIC_LEN; + // not a string with terminated '\0' + if (AsciiStrnCmp (Buffer, Name, HIKEY_PTABLE_HEAD_NAME_LEN) != 0) { + DEBUG ((DEBUG_ERROR, "unknown ptable image\n")); + return NULL; + } + Buffer += HIKEY_PTABLE_HEAD_NAME_LEN; + EntryOffset = *(UINT32 *)Buffer * BlockIo->Media->BlockSize; + Buffer += sizeof (UINT32); + EntrySize = *(UINT32 *)Buffer * BlockIo->Media->BlockSize; + if ((EntrySize + HIKEY_PTABLE_CONTENT_OFFSET) > Size) { + DEBUG ((DEBUG_ERROR, "Entry size doesn't match\n")); + return NULL; + } + Buffer = Image + HIKEY_PTABLE_CONTENT_OFFSET; + Status = DiskIo->WriteDisk (DiskIo, BlockIo->Media->MediaId, EntryOffset, EntrySize, Buffer); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Can't flush partition table\n")); + return NULL; + } + Buffer += EntrySize; + return Buffer; +} + +STATIC +EFI_STATUS +HiKeyFastbootPlatformFlashPartition ( + IN CHAR8 *PartitionName, + IN UINTN Size, + IN VOID *Image + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_DISK_IO_PROTOCOL *DiskIo; + UINT32 MediaId; + UINTN PartitionSize; + FASTBOOT_PARTITION_LIST *Entry; + CHAR16 PartitionNameUnicode[PARTITION_NAME_LENGTH]; + BOOLEAN PartitionFound; + VOID *Buffer; + + + AsciiStrToUnicodeStr (PartitionName, PartitionNameUnicode); + + PartitionFound = FALSE; + Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead)); + while (!IsNull (&mPartitionListHead, &Entry->Link)) { + // Search the partition list for the partition named by PartitionName + if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) { + PartitionFound = TRUE; + break; + } + + Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link); + } + if (!PartitionFound) { + return EFI_NOT_FOUND; + } + + Status = gBS->OpenProtocol ( + Entry->PartitionHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fastboot platform: couldn't open Block IO for flash: %r\n", Status)); + return EFI_NOT_FOUND; + } + + // Check image will fit on device + // LastBlock counts from 0 + PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize; + if (PartitionSize < Size) { + DEBUG ((DEBUG_ERROR, "Partition not big enough.\n")); + DEBUG ((DEBUG_ERROR, "Partition Size:\t%ld\nImage Size:\t%ld\n", PartitionSize, Size)); + + return EFI_VOLUME_FULL; + } + + MediaId = BlockIo->Media->MediaId; + + Status = gBS->OpenProtocol ( + Entry->PartitionHandle, + &gEfiDiskIoProtocolGuid, + (VOID **) &DiskIo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + ASSERT_EFI_ERROR (Status); + + if (AsciiStrCmp (PartitionName, "ptable") == 0) { + Buffer = WritePartition (Image, Size, DiskIo, BlockIo, "primary"); + if (Buffer == NULL) { + return EFI_DEVICE_ERROR; + } + if (Size >= (2 * PartitionSize)) { + Buffer = WritePartition (Buffer, Size, DiskIo, BlockIo, "second"); + if (Buffer == NULL) { + return EFI_DEVICE_ERROR; + } + } + } else { + Status = DiskIo->WriteDisk (DiskIo, MediaId, 0, Size, Image); + } + + BlockIo->FlushBlocks(BlockIo); + // wait DMA finished + MicroSecondDelay (50000); + + return Status; +} + +STATIC +EFI_STATUS +HiKeyFastbootPlatformErasePartition ( + IN CHAR8 *PartitionName + ) +{ + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +HiKeyFastbootPlatformGetVar ( + IN CHAR8 *Name, + OUT CHAR8 *Value + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + UINT64 PartitionSize; + FASTBOOT_PARTITION_LIST *Entry; + CHAR16 PartitionNameUnicode[PARTITION_NAME_LENGTH]; + BOOLEAN PartitionFound; + CHAR16 DataUnicode[SERIAL_NUMBER_LENGTH + 1]; // terminated '\0' + UINTN VariableSize; + CHAR8 PartTypeStr[] = "partition-type"; + CHAR8 PartSizeStr[] = "partition-size"; + + if (!AsciiStrCmp (Name, "max-download-size")) { + AsciiStrCpy (Value, FixedPcdGetPtr (PcdArmFastbootFlashLimit)); + } else if (!AsciiStrCmp (Name, "product")) { + AsciiStrCpy (Value, FixedPcdGetPtr (PcdFirmwareVendor)); + } else if (!AsciiStrCmp (Name, "serialno")) { + VariableSize = (SERIAL_NUMBER_LENGTH + 1) * sizeof (CHAR16); + Status = gRT->GetVariable ( + (CHAR16 *)L"SerialNo", + &gHiKeyVariableGuid, + NULL, + &VariableSize, + &DataUnicode + ); + if (EFI_ERROR (Status)) { + *Value = '\0'; + return EFI_NOT_FOUND; + } + DataUnicode[SERIAL_NUMBER_LENGTH * sizeof(CHAR16)] = '\0'; + UnicodeStrToAsciiStr (DataUnicode, Value); + } else if (!AsciiStrnCmp (Name, PartSizeStr, AsciiStrLen (PartSizeStr))) { + // skip ':', then copy + AsciiStrToUnicodeStr ((Name + AsciiStrLen (PartSizeStr) + 1), PartitionNameUnicode); + PartitionFound = FALSE; + Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead)); + while (!IsNull (&mPartitionListHead, &Entry->Link)) { + // Search the partition list for the partition named by PartitionName + if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) { + PartitionFound = TRUE; + break; + } + + Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link); + } + if (!PartitionFound) { + *Value = '\0'; + return EFI_NOT_FOUND; + } + + Status = gBS->OpenProtocol ( + Entry->PartitionHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fastboot platform: couldn't open Block IO for flash: %r\n", Status)); + *Value = '\0'; + return EFI_NOT_FOUND; + } + + // LastBlock counts from 0 + PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize; + DEBUG ((DEBUG_INFO, "Fastboot platform: check for partition-size:%a 0x%llx\n", Name, PartitionSize)); + AsciiSPrint (Value, PARTITION_SIZE_LENGTH, "0x%llx", PartitionSize); + } else if ( !AsciiStrnCmp (Name, PartTypeStr, AsciiStrLen (PartTypeStr))) { + DEBUG ((DEBUG_INFO, "Fastboot platform: check for partition-type:%a\n", Name + AsciiStrLen (PartTypeStr))); + // skip ':' + if (!AsciiStrCmp ((Name + AsciiStrLen (PartTypeStr) + 1) , "system") || + !AsciiStrCmp ((Name + AsciiStrLen (PartTypeStr) + 1) , "userdata") || + !AsciiStrCmp ((Name + AsciiStrLen (PartTypeStr) + 1) , "cache")) { + AsciiStrCpy (Value, "ext4"); + } else { + AsciiStrCpy (Value, "raw"); + } + } else { + *Value = '\0'; + } + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +HiKeyFastbootPlatformOemCommand ( + IN CHAR8 *Command + ) +{ + if (AsciiStrCmp (Command, "Demonstrate") == 0) { + DEBUG ((DEBUG_ERROR, "ARM OEM Fastboot command 'Demonstrate' received.\n")); + return EFI_SUCCESS; + } else { + DEBUG ((DEBUG_ERROR, + "HiKey: Unrecognised Fastboot OEM command: %s\n", + Command + )); + return EFI_NOT_FOUND; + } +} + +FASTBOOT_PLATFORM_PROTOCOL mPlatformProtocol = { + HiKeyFastbootPlatformInit, + HiKeyFastbootPlatformUnInit, + HiKeyFastbootPlatformFlashPartition, + HiKeyFastbootPlatformErasePartition, + HiKeyFastbootPlatformGetVar, + HiKeyFastbootPlatformOemCommand +}; + +EFI_STATUS +EFIAPI +HiKeyFastbootPlatformEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return gBS->InstallProtocolInterface ( + &ImageHandle, + &gAndroidFastbootPlatformProtocolGuid, + EFI_NATIVE_INTERFACE, + &mPlatformProtocol + ); +} diff --git a/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf new file mode 100644 index 0000000..353c6c3 --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf @@ -0,0 +1,61 @@ +#/** @file +# +# Copyright (c) 2014, ARM Ltd. All rights reserved.<BR> +# Copyright (c) 2015-2017, Linaro. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = HiKeyFastbootDxe + FILE_GUID = 8e335c38-c4e1-494e-8011-37a858d9763d + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = HiKeyFastbootPlatformEntryPoint + +[Sources.common] + HiKeyFastbootDxe.c + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DevicePathLib + MemoryAllocationLib + PcdLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + TimerLib + +[Protocols] + gAndroidFastbootPlatformProtocolGuid + gEfiBlockIoProtocolGuid + gEfiDiskIoProtocolGuid + gEfiSimpleTextOutProtocolGuid + gEfiEraseBlockProtocolGuid + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec + ArmPkg/ArmPkg.dec + OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKey.dec + +[Guids] + gHiKeyVariableGuid + +[Pcd] + gArmPlatformTokenSpaceGuid.PcdFirmwareVendor + gHiKeyTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath + gHiKeyTokenSpaceGuid.PcdArmFastbootFlashLimit diff --git a/Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h b/Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h new file mode 100644 index 0000000..56d5a0e --- /dev/null +++ b/Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h @@ -0,0 +1,24 @@ +/** @file +* +* Copyright (c) 2013-2014, ARM Limited. All rights reserved. +* Copyright (c) 2015-2017, Linaro. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#ifndef __HIKEY_VARIABLE_H__ +#define __HIKEY_VARIABLE_H__ + +#define HIKEY_VARIABLE_GUID \ + { 0x66b8d063, 0x1daa, 0x4c60, { 0xb9, 0xf2, 0x55, 0x0d, 0x7e, 0xe1, 0x2f, 0x38 } } + +extern EFI_GUID gHiKeyVariableGuid; + +#endif /* __HIKEY_VARIABLE_H__ */
Support HiKey Fastboot driver for Fastboot App. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org> --- Platforms/Hisilicon/HiKey/HiKey.dec | 1 + .../HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c | 672 +++++++++++++++++++++ .../HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf | 61 ++ .../Hisilicon/HiKey/Include/Guid/HiKeyVariable.h | 24 + 4 files changed, 758 insertions(+) create mode 100644 Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c create mode 100644 Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf create mode 100644 Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h