181f2915669f734f34e3e83c83287e7371e298390Olivier Martin/** @file 281f2915669f734f34e3e83c83287e7371e298390Olivier Martin 381f2915669f734f34e3e83c83287e7371e298390Olivier Martin Copyright (c) 2014, ARM Ltd. All rights reserved.<BR> 481f2915669f734f34e3e83c83287e7371e298390Olivier Martin 581f2915669f734f34e3e83c83287e7371e298390Olivier Martin This program and the accompanying materials 681f2915669f734f34e3e83c83287e7371e298390Olivier Martin are licensed and made available under the terms and conditions of the BSD License 781f2915669f734f34e3e83c83287e7371e298390Olivier Martin which accompanies this distribution. The full text of the license may be found at 881f2915669f734f34e3e83c83287e7371e298390Olivier Martin http://opensource.org/licenses/bsd-license.php 981f2915669f734f34e3e83c83287e7371e298390Olivier Martin 1081f2915669f734f34e3e83c83287e7371e298390Olivier Martin THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 1181f2915669f734f34e3e83c83287e7371e298390Olivier Martin WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 1281f2915669f734f34e3e83c83287e7371e298390Olivier Martin 1381f2915669f734f34e3e83c83287e7371e298390Olivier Martin**/ 1481f2915669f734f34e3e83c83287e7371e298390Olivier Martin 1581f2915669f734f34e3e83c83287e7371e298390Olivier Martin/* 1681f2915669f734f34e3e83c83287e7371e298390Olivier Martin Implementation of the Android Fastboot Platform protocol, to be used by the 1781f2915669f734f34e3e83c83287e7371e298390Olivier Martin Fastboot UEFI application, for ARM Versatile Express platforms. 1881f2915669f734f34e3e83c83287e7371e298390Olivier Martin*/ 1981f2915669f734f34e3e83c83287e7371e298390Olivier Martin 2081f2915669f734f34e3e83c83287e7371e298390Olivier Martin#include <Protocol/AndroidFastbootPlatform.h> 2181f2915669f734f34e3e83c83287e7371e298390Olivier Martin#include <Protocol/BlockIo.h> 2281f2915669f734f34e3e83c83287e7371e298390Olivier Martin#include <Protocol/DiskIo.h> 2381f2915669f734f34e3e83c83287e7371e298390Olivier Martin 2481f2915669f734f34e3e83c83287e7371e298390Olivier Martin#include <Library/BaseLib.h> 2581f2915669f734f34e3e83c83287e7371e298390Olivier Martin#include <Library/BaseMemoryLib.h> 2681f2915669f734f34e3e83c83287e7371e298390Olivier Martin#include <Library/DebugLib.h> 2781f2915669f734f34e3e83c83287e7371e298390Olivier Martin#include <Library/DevicePathLib.h> 2881f2915669f734f34e3e83c83287e7371e298390Olivier Martin#include <Library/MemoryAllocationLib.h> 2981f2915669f734f34e3e83c83287e7371e298390Olivier Martin#include <Library/UefiBootServicesTableLib.h> 3081f2915669f734f34e3e83c83287e7371e298390Olivier Martin 3181f2915669f734f34e3e83c83287e7371e298390Olivier Martin#define FLASH_DEVICE_PATH_SIZE(DevPath) ( GetDevicePathSize (DevPath) - \ 3281f2915669f734f34e3e83c83287e7371e298390Olivier Martin sizeof (EFI_DEVICE_PATH_PROTOCOL)) 3381f2915669f734f34e3e83c83287e7371e298390Olivier Martin 3481f2915669f734f34e3e83c83287e7371e298390Olivier Martin#define PARTITION_NAME_MAX_LENGTH 72/2 3581f2915669f734f34e3e83c83287e7371e298390Olivier Martin 3681f2915669f734f34e3e83c83287e7371e298390Olivier Martin#define IS_ALPHA(Char) (((Char) <= L'z' && (Char) >= L'a') || \ 3781f2915669f734f34e3e83c83287e7371e298390Olivier Martin ((Char) <= L'Z' && (Char) >= L'Z')) 3881f2915669f734f34e3e83c83287e7371e298390Olivier Martin 3981f2915669f734f34e3e83c83287e7371e298390Olivier Martintypedef struct _FASTBOOT_PARTITION_LIST { 4081f2915669f734f34e3e83c83287e7371e298390Olivier Martin LIST_ENTRY Link; 4181f2915669f734f34e3e83c83287e7371e298390Olivier Martin CHAR16 PartitionName[PARTITION_NAME_MAX_LENGTH]; 4281f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_HANDLE PartitionHandle; 4381f2915669f734f34e3e83c83287e7371e298390Olivier Martin} FASTBOOT_PARTITION_LIST; 4481f2915669f734f34e3e83c83287e7371e298390Olivier Martin 4581f2915669f734f34e3e83c83287e7371e298390Olivier MartinSTATIC LIST_ENTRY mPartitionListHead; 4681f2915669f734f34e3e83c83287e7371e298390Olivier Martin 4781f2915669f734f34e3e83c83287e7371e298390Olivier Martin/* 4881f2915669f734f34e3e83c83287e7371e298390Olivier Martin Helper to free the partition list 4981f2915669f734f34e3e83c83287e7371e298390Olivier Martin*/ 5081f2915669f734f34e3e83c83287e7371e298390Olivier MartinSTATIC 5181f2915669f734f34e3e83c83287e7371e298390Olivier MartinVOID 5281f2915669f734f34e3e83c83287e7371e298390Olivier MartinFreePartitionList ( 5381f2915669f734f34e3e83c83287e7371e298390Olivier Martin VOID 5481f2915669f734f34e3e83c83287e7371e298390Olivier Martin ) 5581f2915669f734f34e3e83c83287e7371e298390Olivier Martin{ 5681f2915669f734f34e3e83c83287e7371e298390Olivier Martin FASTBOOT_PARTITION_LIST *Entry; 5781f2915669f734f34e3e83c83287e7371e298390Olivier Martin FASTBOOT_PARTITION_LIST *NextEntry; 5881f2915669f734f34e3e83c83287e7371e298390Olivier Martin 5981f2915669f734f34e3e83c83287e7371e298390Olivier Martin Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&mPartitionListHead); 6081f2915669f734f34e3e83c83287e7371e298390Olivier Martin while (!IsNull (&mPartitionListHead, &Entry->Link)) { 6181f2915669f734f34e3e83c83287e7371e298390Olivier Martin NextEntry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &Entry->Link); 6281f2915669f734f34e3e83c83287e7371e298390Olivier Martin 6381f2915669f734f34e3e83c83287e7371e298390Olivier Martin RemoveEntryList (&Entry->Link); 6481f2915669f734f34e3e83c83287e7371e298390Olivier Martin FreePool (Entry); 6581f2915669f734f34e3e83c83287e7371e298390Olivier Martin 6681f2915669f734f34e3e83c83287e7371e298390Olivier Martin Entry = NextEntry; 6781f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 6881f2915669f734f34e3e83c83287e7371e298390Olivier Martin} 6981f2915669f734f34e3e83c83287e7371e298390Olivier Martin/* 7081f2915669f734f34e3e83c83287e7371e298390Olivier Martin Read the PartitionName fields from the GPT partition entries, putting them 7181f2915669f734f34e3e83c83287e7371e298390Olivier Martin into an allocated array that should later be freed. 7281f2915669f734f34e3e83c83287e7371e298390Olivier Martin*/ 7381f2915669f734f34e3e83c83287e7371e298390Olivier MartinSTATIC 7481f2915669f734f34e3e83c83287e7371e298390Olivier MartinEFI_STATUS 7581f2915669f734f34e3e83c83287e7371e298390Olivier MartinReadPartitionEntries ( 7681f2915669f734f34e3e83c83287e7371e298390Olivier Martin IN EFI_BLOCK_IO_PROTOCOL *BlockIo, 7781f2915669f734f34e3e83c83287e7371e298390Olivier Martin OUT EFI_PARTITION_ENTRY **PartitionEntries 7881f2915669f734f34e3e83c83287e7371e298390Olivier Martin ) 7981f2915669f734f34e3e83c83287e7371e298390Olivier Martin{ 8081f2915669f734f34e3e83c83287e7371e298390Olivier Martin UINTN EntrySize; 8181f2915669f734f34e3e83c83287e7371e298390Olivier Martin UINTN NumEntries; 8281f2915669f734f34e3e83c83287e7371e298390Olivier Martin UINTN BufferSize; 8381f2915669f734f34e3e83c83287e7371e298390Olivier Martin UINT32 MediaId; 8481f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_PARTITION_TABLE_HEADER *GptHeader; 8581f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_STATUS Status; 8681f2915669f734f34e3e83c83287e7371e298390Olivier Martin 8781f2915669f734f34e3e83c83287e7371e298390Olivier Martin MediaId = BlockIo->Media->MediaId; 8881f2915669f734f34e3e83c83287e7371e298390Olivier Martin 8981f2915669f734f34e3e83c83287e7371e298390Olivier Martin // 9081f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Read size of Partition entry and number of entries from GPT header 9181f2915669f734f34e3e83c83287e7371e298390Olivier Martin // 9281f2915669f734f34e3e83c83287e7371e298390Olivier Martin 9381f2915669f734f34e3e83c83287e7371e298390Olivier Martin GptHeader = AllocatePool (BlockIo->Media->BlockSize); 9481f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (GptHeader == NULL) { 9581f2915669f734f34e3e83c83287e7371e298390Olivier Martin return EFI_OUT_OF_RESOURCES; 9681f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 9781f2915669f734f34e3e83c83287e7371e298390Olivier Martin 9881f2915669f734f34e3e83c83287e7371e298390Olivier Martin Status = BlockIo->ReadBlocks (BlockIo, MediaId, 1, BlockIo->Media->BlockSize, (VOID *) GptHeader); 9981f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (EFI_ERROR (Status)) { 10081f2915669f734f34e3e83c83287e7371e298390Olivier Martin return Status; 10181f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 10281f2915669f734f34e3e83c83287e7371e298390Olivier Martin 10381f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Check there is a GPT on the media 10481f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (GptHeader->Header.Signature != EFI_PTAB_HEADER_ID || 10581f2915669f734f34e3e83c83287e7371e298390Olivier Martin GptHeader->MyLBA != 1) { 10681f2915669f734f34e3e83c83287e7371e298390Olivier Martin DEBUG ((EFI_D_ERROR, 10781f2915669f734f34e3e83c83287e7371e298390Olivier Martin "Fastboot platform: No GPT on flash. " 10881f2915669f734f34e3e83c83287e7371e298390Olivier Martin "Fastboot on Versatile Express does not support MBR.\n" 10981f2915669f734f34e3e83c83287e7371e298390Olivier Martin )); 11081f2915669f734f34e3e83c83287e7371e298390Olivier Martin return EFI_DEVICE_ERROR; 11181f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 11281f2915669f734f34e3e83c83287e7371e298390Olivier Martin 11381f2915669f734f34e3e83c83287e7371e298390Olivier Martin EntrySize = GptHeader->SizeOfPartitionEntry; 11481f2915669f734f34e3e83c83287e7371e298390Olivier Martin NumEntries = GptHeader->NumberOfPartitionEntries; 11581f2915669f734f34e3e83c83287e7371e298390Olivier Martin 11681f2915669f734f34e3e83c83287e7371e298390Olivier Martin FreePool (GptHeader); 11781f2915669f734f34e3e83c83287e7371e298390Olivier Martin 11881f2915669f734f34e3e83c83287e7371e298390Olivier Martin ASSERT (EntrySize != 0); 11981f2915669f734f34e3e83c83287e7371e298390Olivier Martin ASSERT (NumEntries != 0); 12081f2915669f734f34e3e83c83287e7371e298390Olivier Martin 12181f2915669f734f34e3e83c83287e7371e298390Olivier Martin BufferSize = ALIGN_VALUE (EntrySize * NumEntries, BlockIo->Media->BlockSize); 12281f2915669f734f34e3e83c83287e7371e298390Olivier Martin *PartitionEntries = AllocatePool (BufferSize); 12381f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (PartitionEntries == NULL) { 12481f2915669f734f34e3e83c83287e7371e298390Olivier Martin return EFI_OUT_OF_RESOURCES; 12581f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 12681f2915669f734f34e3e83c83287e7371e298390Olivier Martin 12781f2915669f734f34e3e83c83287e7371e298390Olivier Martin Status = BlockIo->ReadBlocks (BlockIo, MediaId, 2, BufferSize, (VOID *) *PartitionEntries); 12881f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (EFI_ERROR (Status)) { 12981f2915669f734f34e3e83c83287e7371e298390Olivier Martin FreePool (PartitionEntries); 13081f2915669f734f34e3e83c83287e7371e298390Olivier Martin return Status; 13181f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 13281f2915669f734f34e3e83c83287e7371e298390Olivier Martin 13381f2915669f734f34e3e83c83287e7371e298390Olivier Martin return Status; 13481f2915669f734f34e3e83c83287e7371e298390Olivier Martin} 13581f2915669f734f34e3e83c83287e7371e298390Olivier Martin 13681f2915669f734f34e3e83c83287e7371e298390Olivier Martin 13781f2915669f734f34e3e83c83287e7371e298390Olivier Martin/* 13881f2915669f734f34e3e83c83287e7371e298390Olivier Martin Initialise: Open the Android NVM device and find the partitions on it. Save them in 13981f2915669f734f34e3e83c83287e7371e298390Olivier Martin a list along with the "PartitionName" fields for their GPT entries. 14081f2915669f734f34e3e83c83287e7371e298390Olivier Martin We will use these partition names as the key in 14181f2915669f734f34e3e83c83287e7371e298390Olivier Martin ArmFastbootPlatformFlashPartition. 14281f2915669f734f34e3e83c83287e7371e298390Olivier Martin*/ 14381f2915669f734f34e3e83c83287e7371e298390Olivier MartinEFI_STATUS 14481f2915669f734f34e3e83c83287e7371e298390Olivier MartinArmFastbootPlatformInit ( 14581f2915669f734f34e3e83c83287e7371e298390Olivier Martin VOID 14681f2915669f734f34e3e83c83287e7371e298390Olivier Martin ) 14781f2915669f734f34e3e83c83287e7371e298390Olivier Martin{ 14881f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_STATUS Status; 14981f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_DEVICE_PATH_PROTOCOL *FlashDevicePath; 15081f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_DEVICE_PATH_PROTOCOL *FlashDevicePathDup; 15181f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_DEVICE_PATH_PROTOCOL *DevicePath; 15281f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_DEVICE_PATH_PROTOCOL *NextNode; 15381f2915669f734f34e3e83c83287e7371e298390Olivier Martin HARDDRIVE_DEVICE_PATH *PartitionNode; 15481f2915669f734f34e3e83c83287e7371e298390Olivier Martin UINTN NumHandles; 15581f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_HANDLE *AllHandles; 15681f2915669f734f34e3e83c83287e7371e298390Olivier Martin UINTN LoopIndex; 15781f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_HANDLE FlashHandle; 15881f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_BLOCK_IO_PROTOCOL *FlashBlockIo; 15981f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_PARTITION_ENTRY *PartitionEntries; 16081f2915669f734f34e3e83c83287e7371e298390Olivier Martin FASTBOOT_PARTITION_LIST *Entry; 16181f2915669f734f34e3e83c83287e7371e298390Olivier Martin 16281f2915669f734f34e3e83c83287e7371e298390Olivier Martin InitializeListHead (&mPartitionListHead); 16381f2915669f734f34e3e83c83287e7371e298390Olivier Martin 16481f2915669f734f34e3e83c83287e7371e298390Olivier Martin // 16581f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Get EFI_HANDLES for all the partitions on the block devices pointed to by 16681f2915669f734f34e3e83c83287e7371e298390Olivier Martin // PcdFastbootFlashDevicePath, also saving their GPT partition labels. 16781f2915669f734f34e3e83c83287e7371e298390Olivier Martin // There's no way to find all of a device's children, so we get every handle 16881f2915669f734f34e3e83c83287e7371e298390Olivier Martin // in the system supporting EFI_BLOCK_IO_PROTOCOL and then filter out ones 16981f2915669f734f34e3e83c83287e7371e298390Olivier Martin // that don't represent partitions on the flash device. 17081f2915669f734f34e3e83c83287e7371e298390Olivier Martin // 17181f2915669f734f34e3e83c83287e7371e298390Olivier Martin 17281f2915669f734f34e3e83c83287e7371e298390Olivier Martin FlashDevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdAndroidFastbootNvmDevicePath)); 17381f2915669f734f34e3e83c83287e7371e298390Olivier Martin 17481f2915669f734f34e3e83c83287e7371e298390Olivier Martin // 17581f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Open the Disk IO protocol on the flash device - this will be used to read 17681f2915669f734f34e3e83c83287e7371e298390Olivier Martin // partition names out of the GPT entries 17781f2915669f734f34e3e83c83287e7371e298390Olivier Martin // 17881f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Create another device path pointer because LocateDevicePath will modify it. 17981f2915669f734f34e3e83c83287e7371e298390Olivier Martin FlashDevicePathDup = FlashDevicePath; 18081f2915669f734f34e3e83c83287e7371e298390Olivier Martin Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &FlashDevicePathDup, &FlashHandle); 18181f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (EFI_ERROR (Status)) { 18281f2915669f734f34e3e83c83287e7371e298390Olivier Martin DEBUG ((EFI_D_ERROR, "Warning: Couldn't locate Android NVM device (status: %r)\n", Status)); 18381f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Failing to locate partitions should not prevent to do other Android FastBoot actions 18481f2915669f734f34e3e83c83287e7371e298390Olivier Martin return EFI_SUCCESS; 18581f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 18681f2915669f734f34e3e83c83287e7371e298390Olivier Martin 18781f2915669f734f34e3e83c83287e7371e298390Olivier Martin Status = gBS->OpenProtocol ( 18881f2915669f734f34e3e83c83287e7371e298390Olivier Martin FlashHandle, 18981f2915669f734f34e3e83c83287e7371e298390Olivier Martin &gEfiBlockIoProtocolGuid, 19081f2915669f734f34e3e83c83287e7371e298390Olivier Martin (VOID **) &FlashBlockIo, 19181f2915669f734f34e3e83c83287e7371e298390Olivier Martin gImageHandle, 19281f2915669f734f34e3e83c83287e7371e298390Olivier Martin NULL, 19381f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_OPEN_PROTOCOL_GET_PROTOCOL 19481f2915669f734f34e3e83c83287e7371e298390Olivier Martin ); 19581f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (EFI_ERROR (Status)) { 19681f2915669f734f34e3e83c83287e7371e298390Olivier Martin DEBUG ((EFI_D_ERROR, "Fastboot platform: Couldn't open Android NVM device (status: %r)\n", Status)); 19781f2915669f734f34e3e83c83287e7371e298390Olivier Martin return EFI_DEVICE_ERROR; 19881f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 19981f2915669f734f34e3e83c83287e7371e298390Olivier Martin 20081f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Read the GPT partition entry array into memory so we can get the partition names 20181f2915669f734f34e3e83c83287e7371e298390Olivier Martin Status = ReadPartitionEntries (FlashBlockIo, &PartitionEntries); 20281f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (EFI_ERROR (Status)) { 20391c38d4e94c1461f5824b83d3722fe46626aa0d3Ronald Cron DEBUG ((EFI_D_ERROR, "Warning: Failed to read partitions from Android NVM device (status: %r)\n", Status)); 20491c38d4e94c1461f5824b83d3722fe46626aa0d3Ronald Cron // Failing to locate partitions should not prevent to do other Android FastBoot actions 20591c38d4e94c1461f5824b83d3722fe46626aa0d3Ronald Cron return EFI_SUCCESS; 20681f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 20781f2915669f734f34e3e83c83287e7371e298390Olivier Martin 20881f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Get every Block IO protocol instance installed in the system 20981f2915669f734f34e3e83c83287e7371e298390Olivier Martin Status = gBS->LocateHandleBuffer ( 21081f2915669f734f34e3e83c83287e7371e298390Olivier Martin ByProtocol, 21181f2915669f734f34e3e83c83287e7371e298390Olivier Martin &gEfiBlockIoProtocolGuid, 21281f2915669f734f34e3e83c83287e7371e298390Olivier Martin NULL, 21381f2915669f734f34e3e83c83287e7371e298390Olivier Martin &NumHandles, 21481f2915669f734f34e3e83c83287e7371e298390Olivier Martin &AllHandles 21581f2915669f734f34e3e83c83287e7371e298390Olivier Martin ); 21681f2915669f734f34e3e83c83287e7371e298390Olivier Martin ASSERT_EFI_ERROR (Status); 21781f2915669f734f34e3e83c83287e7371e298390Olivier Martin 21881f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Filter out handles that aren't children of the flash device 21981f2915669f734f34e3e83c83287e7371e298390Olivier Martin for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) { 22081f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Get the device path for the handle 22181f2915669f734f34e3e83c83287e7371e298390Olivier Martin Status = gBS->OpenProtocol ( 22281f2915669f734f34e3e83c83287e7371e298390Olivier Martin AllHandles[LoopIndex], 22381f2915669f734f34e3e83c83287e7371e298390Olivier Martin &gEfiDevicePathProtocolGuid, 22481f2915669f734f34e3e83c83287e7371e298390Olivier Martin (VOID **) &DevicePath, 22581f2915669f734f34e3e83c83287e7371e298390Olivier Martin gImageHandle, 22681f2915669f734f34e3e83c83287e7371e298390Olivier Martin NULL, 22781f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_OPEN_PROTOCOL_GET_PROTOCOL 22881f2915669f734f34e3e83c83287e7371e298390Olivier Martin ); 22981f2915669f734f34e3e83c83287e7371e298390Olivier Martin ASSERT_EFI_ERROR (Status); 23081f2915669f734f34e3e83c83287e7371e298390Olivier Martin 23181f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Check if it is a sub-device of the flash device 23281f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (!CompareMem (DevicePath, FlashDevicePath, FLASH_DEVICE_PATH_SIZE (FlashDevicePath))) { 23381f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Device path starts with path of flash device. Check it isn't the flash 23481f2915669f734f34e3e83c83287e7371e298390Olivier Martin // device itself. 23581f2915669f734f34e3e83c83287e7371e298390Olivier Martin NextNode = NextDevicePathNode (DevicePath); 23681f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (IsDevicePathEndType (NextNode)) { 23781f2915669f734f34e3e83c83287e7371e298390Olivier Martin continue; 23881f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 23981f2915669f734f34e3e83c83287e7371e298390Olivier Martin 24081f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Assert that this device path node represents a partition. 24181f2915669f734f34e3e83c83287e7371e298390Olivier Martin ASSERT (NextNode->Type == MEDIA_DEVICE_PATH && 24281f2915669f734f34e3e83c83287e7371e298390Olivier Martin NextNode->SubType == MEDIA_HARDDRIVE_DP); 24381f2915669f734f34e3e83c83287e7371e298390Olivier Martin 24481f2915669f734f34e3e83c83287e7371e298390Olivier Martin PartitionNode = (HARDDRIVE_DEVICE_PATH *) NextNode; 24581f2915669f734f34e3e83c83287e7371e298390Olivier Martin 24681f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Assert that the partition type is GPT. ReadPartitionEntries checks for 24781f2915669f734f34e3e83c83287e7371e298390Olivier Martin // presence of a GPT, so we should never find MBR partitions. 24881f2915669f734f34e3e83c83287e7371e298390Olivier Martin // ("MBRType" is a misnomer - this field is actually called "Partition 24981f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Format") 25081f2915669f734f34e3e83c83287e7371e298390Olivier Martin ASSERT (PartitionNode->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER); 25181f2915669f734f34e3e83c83287e7371e298390Olivier Martin 25281f2915669f734f34e3e83c83287e7371e298390Olivier Martin // The firmware may install a handle for "partition 0", representing the 25381f2915669f734f34e3e83c83287e7371e298390Olivier Martin // whole device. Ignore it. 25481f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (PartitionNode->PartitionNumber == 0) { 25581f2915669f734f34e3e83c83287e7371e298390Olivier Martin continue; 25681f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 25781f2915669f734f34e3e83c83287e7371e298390Olivier Martin 25881f2915669f734f34e3e83c83287e7371e298390Olivier Martin // 25981f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Add the partition handle to the list 26081f2915669f734f34e3e83c83287e7371e298390Olivier Martin // 26181f2915669f734f34e3e83c83287e7371e298390Olivier Martin 26281f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Create entry 26381f2915669f734f34e3e83c83287e7371e298390Olivier Martin Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST)); 26481f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (Entry == NULL) { 26581f2915669f734f34e3e83c83287e7371e298390Olivier Martin Status = EFI_OUT_OF_RESOURCES; 26681f2915669f734f34e3e83c83287e7371e298390Olivier Martin FreePartitionList (); 26781f2915669f734f34e3e83c83287e7371e298390Olivier Martin goto Exit; 26881f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 26981f2915669f734f34e3e83c83287e7371e298390Olivier Martin 27081f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Copy handle and partition name 27181f2915669f734f34e3e83c83287e7371e298390Olivier Martin Entry->PartitionHandle = AllHandles[LoopIndex]; 27281f2915669f734f34e3e83c83287e7371e298390Olivier Martin StrnCpy ( 27381f2915669f734f34e3e83c83287e7371e298390Olivier Martin Entry->PartitionName, 27481f2915669f734f34e3e83c83287e7371e298390Olivier Martin PartitionEntries[PartitionNode->PartitionNumber - 1].PartitionName, // Partition numbers start from 1. 27581f2915669f734f34e3e83c83287e7371e298390Olivier Martin PARTITION_NAME_MAX_LENGTH 27681f2915669f734f34e3e83c83287e7371e298390Olivier Martin ); 27781f2915669f734f34e3e83c83287e7371e298390Olivier Martin InsertTailList (&mPartitionListHead, &Entry->Link); 27881f2915669f734f34e3e83c83287e7371e298390Olivier Martin 27981f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Print a debug message if the partition label is empty or looks like 28081f2915669f734f34e3e83c83287e7371e298390Olivier Martin // garbage. 28181f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (!IS_ALPHA (Entry->PartitionName[0])) { 28281f2915669f734f34e3e83c83287e7371e298390Olivier Martin DEBUG ((EFI_D_ERROR, 28381f2915669f734f34e3e83c83287e7371e298390Olivier Martin "Warning: Partition %d doesn't seem to have a GPT partition label. " 28481f2915669f734f34e3e83c83287e7371e298390Olivier Martin "You won't be able to flash it with Fastboot.\n", 28581f2915669f734f34e3e83c83287e7371e298390Olivier Martin PartitionNode->PartitionNumber 28681f2915669f734f34e3e83c83287e7371e298390Olivier Martin )); 28781f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 28881f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 28981f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 29081f2915669f734f34e3e83c83287e7371e298390Olivier Martin 29181f2915669f734f34e3e83c83287e7371e298390Olivier MartinExit: 29281f2915669f734f34e3e83c83287e7371e298390Olivier Martin FreePool (PartitionEntries); 29381f2915669f734f34e3e83c83287e7371e298390Olivier Martin FreePool (FlashDevicePath); 29481f2915669f734f34e3e83c83287e7371e298390Olivier Martin FreePool (AllHandles); 29581f2915669f734f34e3e83c83287e7371e298390Olivier Martin return Status; 29681f2915669f734f34e3e83c83287e7371e298390Olivier Martin 29781f2915669f734f34e3e83c83287e7371e298390Olivier Martin} 29881f2915669f734f34e3e83c83287e7371e298390Olivier Martin 29981f2915669f734f34e3e83c83287e7371e298390Olivier MartinVOID 30081f2915669f734f34e3e83c83287e7371e298390Olivier MartinArmFastbootPlatformUnInit ( 30181f2915669f734f34e3e83c83287e7371e298390Olivier Martin VOID 30281f2915669f734f34e3e83c83287e7371e298390Olivier Martin ) 30381f2915669f734f34e3e83c83287e7371e298390Olivier Martin{ 30481f2915669f734f34e3e83c83287e7371e298390Olivier Martin FreePartitionList (); 30581f2915669f734f34e3e83c83287e7371e298390Olivier Martin} 30681f2915669f734f34e3e83c83287e7371e298390Olivier Martin 30781f2915669f734f34e3e83c83287e7371e298390Olivier MartinEFI_STATUS 30881f2915669f734f34e3e83c83287e7371e298390Olivier MartinArmFastbootPlatformFlashPartition ( 30981f2915669f734f34e3e83c83287e7371e298390Olivier Martin IN CHAR8 *PartitionName, 31081f2915669f734f34e3e83c83287e7371e298390Olivier Martin IN UINTN Size, 31181f2915669f734f34e3e83c83287e7371e298390Olivier Martin IN VOID *Image 31281f2915669f734f34e3e83c83287e7371e298390Olivier Martin ) 31381f2915669f734f34e3e83c83287e7371e298390Olivier Martin{ 31481f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_STATUS Status; 31581f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_BLOCK_IO_PROTOCOL *BlockIo; 31681f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_DISK_IO_PROTOCOL *DiskIo; 31781f2915669f734f34e3e83c83287e7371e298390Olivier Martin UINT32 MediaId; 31881f2915669f734f34e3e83c83287e7371e298390Olivier Martin UINTN PartitionSize; 31981f2915669f734f34e3e83c83287e7371e298390Olivier Martin FASTBOOT_PARTITION_LIST *Entry; 32081f2915669f734f34e3e83c83287e7371e298390Olivier Martin CHAR16 PartitionNameUnicode[60]; 32181f2915669f734f34e3e83c83287e7371e298390Olivier Martin BOOLEAN PartitionFound; 322026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio SPARSE_HEADER *SparseHeader; 323026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio CHUNK_HEADER *ChunkHeader; 324026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio UINTN Offset = 0; 325026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio UINT32 Chunk; 326026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio 32781f2915669f734f34e3e83c83287e7371e298390Olivier Martin 32881f2915669f734f34e3e83c83287e7371e298390Olivier Martin AsciiStrToUnicodeStr (PartitionName, PartitionNameUnicode); 32981f2915669f734f34e3e83c83287e7371e298390Olivier Martin 33081f2915669f734f34e3e83c83287e7371e298390Olivier Martin PartitionFound = FALSE; 33181f2915669f734f34e3e83c83287e7371e298390Olivier Martin Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead)); 33281f2915669f734f34e3e83c83287e7371e298390Olivier Martin while (!IsNull (&mPartitionListHead, &Entry->Link)) { 33381f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Search the partition list for the partition named by PartitionName 33481f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) { 33581f2915669f734f34e3e83c83287e7371e298390Olivier Martin PartitionFound = TRUE; 33681f2915669f734f34e3e83c83287e7371e298390Olivier Martin break; 33781f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 33881f2915669f734f34e3e83c83287e7371e298390Olivier Martin 33981f2915669f734f34e3e83c83287e7371e298390Olivier Martin Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link); 34081f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 34181f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (!PartitionFound) { 34281f2915669f734f34e3e83c83287e7371e298390Olivier Martin return EFI_NOT_FOUND; 34381f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 34481f2915669f734f34e3e83c83287e7371e298390Olivier Martin 34581f2915669f734f34e3e83c83287e7371e298390Olivier Martin Status = gBS->OpenProtocol ( 34681f2915669f734f34e3e83c83287e7371e298390Olivier Martin Entry->PartitionHandle, 34781f2915669f734f34e3e83c83287e7371e298390Olivier Martin &gEfiBlockIoProtocolGuid, 34881f2915669f734f34e3e83c83287e7371e298390Olivier Martin (VOID **) &BlockIo, 34981f2915669f734f34e3e83c83287e7371e298390Olivier Martin gImageHandle, 35081f2915669f734f34e3e83c83287e7371e298390Olivier Martin NULL, 35181f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_OPEN_PROTOCOL_GET_PROTOCOL 35281f2915669f734f34e3e83c83287e7371e298390Olivier Martin ); 35381f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (EFI_ERROR (Status)) { 35481f2915669f734f34e3e83c83287e7371e298390Olivier Martin DEBUG ((EFI_D_ERROR, "Fastboot platform: couldn't open Block IO for flash: %r\n", Status)); 35581f2915669f734f34e3e83c83287e7371e298390Olivier Martin return EFI_NOT_FOUND; 35681f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 35781f2915669f734f34e3e83c83287e7371e298390Olivier Martin 358026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio SparseHeader=(SPARSE_HEADER *)Image; 359026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio 360026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio if (SparseHeader->Magic == SPARSE_HEADER_MAGIC) { 361026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio DEBUG ((EFI_D_INFO, "Sparse Magic: 0x%x Major: %d Minor: %d fhs: %d chs: %d bs: %d tbs: %d tcs: %d checksum: %d \n", 362026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio SparseHeader->Magic, SparseHeader->MajorVersion, SparseHeader->MinorVersion, SparseHeader->FileHeaderSize, 363026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio SparseHeader->ChunkHeaderSize, SparseHeader->BlockSize, SparseHeader->TotalBlocks, 364026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio SparseHeader->TotalChunks, SparseHeader->ImageChecksum)); 365026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio if (SparseHeader->MajorVersion != 1) { 366026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio DEBUG ((EFI_D_ERROR, "Sparse image version %d.%d not supported.\n", 367026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio SparseHeader->MajorVersion, SparseHeader->MinorVersion)); 368026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio return EFI_INVALID_PARAMETER; 369026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio } 370026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio 371026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio Size = SparseHeader->BlockSize * SparseHeader->TotalBlocks; 372026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio } 373026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio 37481f2915669f734f34e3e83c83287e7371e298390Olivier Martin // Check image will fit on device 37581f2915669f734f34e3e83c83287e7371e298390Olivier Martin PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize; 37681f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (PartitionSize < Size) { 37781f2915669f734f34e3e83c83287e7371e298390Olivier Martin DEBUG ((EFI_D_ERROR, "Partition not big enough.\n")); 37881f2915669f734f34e3e83c83287e7371e298390Olivier Martin DEBUG ((EFI_D_ERROR, "Partition Size:\t%d\nImage Size:\t%d\n", PartitionSize, Size)); 37981f2915669f734f34e3e83c83287e7371e298390Olivier Martin 38081f2915669f734f34e3e83c83287e7371e298390Olivier Martin return EFI_VOLUME_FULL; 38181f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 38281f2915669f734f34e3e83c83287e7371e298390Olivier Martin 38381f2915669f734f34e3e83c83287e7371e298390Olivier Martin MediaId = BlockIo->Media->MediaId; 38481f2915669f734f34e3e83c83287e7371e298390Olivier Martin 38581f2915669f734f34e3e83c83287e7371e298390Olivier Martin Status = gBS->OpenProtocol ( 38681f2915669f734f34e3e83c83287e7371e298390Olivier Martin Entry->PartitionHandle, 38781f2915669f734f34e3e83c83287e7371e298390Olivier Martin &gEfiDiskIoProtocolGuid, 38881f2915669f734f34e3e83c83287e7371e298390Olivier Martin (VOID **) &DiskIo, 38981f2915669f734f34e3e83c83287e7371e298390Olivier Martin gImageHandle, 39081f2915669f734f34e3e83c83287e7371e298390Olivier Martin NULL, 39181f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_OPEN_PROTOCOL_GET_PROTOCOL 39281f2915669f734f34e3e83c83287e7371e298390Olivier Martin ); 39381f2915669f734f34e3e83c83287e7371e298390Olivier Martin ASSERT_EFI_ERROR (Status); 39481f2915669f734f34e3e83c83287e7371e298390Olivier Martin 395026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio if (SparseHeader->Magic == SPARSE_HEADER_MAGIC) { 396026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio Image += SparseHeader->FileHeaderSize; 397026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio for (Chunk = 0; Chunk < SparseHeader->TotalChunks; Chunk++) { 398026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio UINTN WriteSize; 399026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio ChunkHeader = (CHUNK_HEADER *)Image; 400026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio DEBUG ((EFI_D_INFO, "Chunk #%d - Type: 0x%x Size: %d TotalSize: %d Offset %d\n", 401026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio (Chunk+1), ChunkHeader->ChunkType, ChunkHeader->ChunkSize, 402026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio ChunkHeader->TotalSize, Offset)); 403026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio Image += sizeof(CHUNK_HEADER); 404026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio WriteSize=(SparseHeader->BlockSize) * ChunkHeader->ChunkSize; 405026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio switch (ChunkHeader->ChunkType) { 406026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio case CHUNK_TYPE_RAW: 407026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio DEBUG ((EFI_D_INFO, "Writing %d at Offset %d\n", WriteSize, Offset)); 408026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio Status = DiskIo->WriteDisk (DiskIo, MediaId, Offset, WriteSize, Image); 409026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio if (EFI_ERROR (Status)) { 410026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio return Status; 411026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio } 412026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio Image+=WriteSize; 413026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio break; 414026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio case CHUNK_TYPE_DONT_CARE: 415026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio break; 416026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio case CHUNK_TYPE_CRC32: 417026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio break; 418026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio default: 419026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio DEBUG ((EFI_D_ERROR, "Unknown Chunk Type: 0x%x")); 420026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio return EFI_PROTOCOL_ERROR; 421026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio } 422026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio Offset += WriteSize; 423026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio } 424026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio } else { 425026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio Status = DiskIo->WriteDisk (DiskIo, MediaId, 0, Size, Image); 426026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio if (EFI_ERROR (Status)) { 427026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio return Status; 428026fae27f87f326759ef0ad35f7f80a96c3e660eRiku Voipio } 42981f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 43081f2915669f734f34e3e83c83287e7371e298390Olivier Martin 43181f2915669f734f34e3e83c83287e7371e298390Olivier Martin BlockIo->FlushBlocks(BlockIo); 43281f2915669f734f34e3e83c83287e7371e298390Olivier Martin 43381f2915669f734f34e3e83c83287e7371e298390Olivier Martin return Status; 43481f2915669f734f34e3e83c83287e7371e298390Olivier Martin} 43581f2915669f734f34e3e83c83287e7371e298390Olivier Martin 43681f2915669f734f34e3e83c83287e7371e298390Olivier MartinEFI_STATUS 43781f2915669f734f34e3e83c83287e7371e298390Olivier MartinArmFastbootPlatformErasePartition ( 43881f2915669f734f34e3e83c83287e7371e298390Olivier Martin IN CHAR8 *Partition 43981f2915669f734f34e3e83c83287e7371e298390Olivier Martin ) 44081f2915669f734f34e3e83c83287e7371e298390Olivier Martin{ 44181f2915669f734f34e3e83c83287e7371e298390Olivier Martin return EFI_SUCCESS; 44281f2915669f734f34e3e83c83287e7371e298390Olivier Martin} 44381f2915669f734f34e3e83c83287e7371e298390Olivier Martin 44481f2915669f734f34e3e83c83287e7371e298390Olivier MartinEFI_STATUS 44581f2915669f734f34e3e83c83287e7371e298390Olivier MartinArmFastbootPlatformGetVar ( 44681f2915669f734f34e3e83c83287e7371e298390Olivier Martin IN CHAR8 *Name, 44781f2915669f734f34e3e83c83287e7371e298390Olivier Martin OUT CHAR8 *Value 44881f2915669f734f34e3e83c83287e7371e298390Olivier Martin ) 44981f2915669f734f34e3e83c83287e7371e298390Olivier Martin{ 45081f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (AsciiStrCmp (Name, "product")) { 45181f2915669f734f34e3e83c83287e7371e298390Olivier Martin AsciiStrCpy (Value, FixedPcdGetPtr (PcdFirmwareVendor)); 45281f2915669f734f34e3e83c83287e7371e298390Olivier Martin } else { 45381f2915669f734f34e3e83c83287e7371e298390Olivier Martin *Value = '\0'; 45481f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 45581f2915669f734f34e3e83c83287e7371e298390Olivier Martin return EFI_SUCCESS; 45681f2915669f734f34e3e83c83287e7371e298390Olivier Martin} 45781f2915669f734f34e3e83c83287e7371e298390Olivier Martin 45881f2915669f734f34e3e83c83287e7371e298390Olivier MartinEFI_STATUS 45981f2915669f734f34e3e83c83287e7371e298390Olivier MartinArmFastbootPlatformOemCommand ( 46081f2915669f734f34e3e83c83287e7371e298390Olivier Martin IN CHAR8 *Command 46181f2915669f734f34e3e83c83287e7371e298390Olivier Martin ) 46281f2915669f734f34e3e83c83287e7371e298390Olivier Martin{ 46381f2915669f734f34e3e83c83287e7371e298390Olivier Martin CHAR16 CommandUnicode[65]; 46481f2915669f734f34e3e83c83287e7371e298390Olivier Martin 46581f2915669f734f34e3e83c83287e7371e298390Olivier Martin AsciiStrToUnicodeStr (Command, CommandUnicode); 46681f2915669f734f34e3e83c83287e7371e298390Olivier Martin 46781f2915669f734f34e3e83c83287e7371e298390Olivier Martin if (AsciiStrCmp (Command, "Demonstrate") == 0) { 46881f2915669f734f34e3e83c83287e7371e298390Olivier Martin DEBUG ((EFI_D_ERROR, "ARM OEM Fastboot command 'Demonstrate' received.\n")); 46981f2915669f734f34e3e83c83287e7371e298390Olivier Martin return EFI_SUCCESS; 47081f2915669f734f34e3e83c83287e7371e298390Olivier Martin } else { 47181f2915669f734f34e3e83c83287e7371e298390Olivier Martin DEBUG ((EFI_D_ERROR, 47281f2915669f734f34e3e83c83287e7371e298390Olivier Martin "VExpress: Unrecognised Fastboot OEM command: %s\n", 47381f2915669f734f34e3e83c83287e7371e298390Olivier Martin CommandUnicode 47481f2915669f734f34e3e83c83287e7371e298390Olivier Martin )); 47581f2915669f734f34e3e83c83287e7371e298390Olivier Martin return EFI_NOT_FOUND; 47681f2915669f734f34e3e83c83287e7371e298390Olivier Martin } 47781f2915669f734f34e3e83c83287e7371e298390Olivier Martin} 47881f2915669f734f34e3e83c83287e7371e298390Olivier Martin 47981f2915669f734f34e3e83c83287e7371e298390Olivier MartinFASTBOOT_PLATFORM_PROTOCOL mPlatformProtocol = { 48081f2915669f734f34e3e83c83287e7371e298390Olivier Martin ArmFastbootPlatformInit, 48181f2915669f734f34e3e83c83287e7371e298390Olivier Martin ArmFastbootPlatformUnInit, 48281f2915669f734f34e3e83c83287e7371e298390Olivier Martin ArmFastbootPlatformFlashPartition, 48381f2915669f734f34e3e83c83287e7371e298390Olivier Martin ArmFastbootPlatformErasePartition, 48481f2915669f734f34e3e83c83287e7371e298390Olivier Martin ArmFastbootPlatformGetVar, 48581f2915669f734f34e3e83c83287e7371e298390Olivier Martin ArmFastbootPlatformOemCommand 48681f2915669f734f34e3e83c83287e7371e298390Olivier Martin}; 48781f2915669f734f34e3e83c83287e7371e298390Olivier Martin 48881f2915669f734f34e3e83c83287e7371e298390Olivier MartinEFI_STATUS 48981f2915669f734f34e3e83c83287e7371e298390Olivier MartinEFIAPI 49081f2915669f734f34e3e83c83287e7371e298390Olivier MartinArmAndroidFastbootPlatformEntryPoint ( 49181f2915669f734f34e3e83c83287e7371e298390Olivier Martin IN EFI_HANDLE ImageHandle, 49281f2915669f734f34e3e83c83287e7371e298390Olivier Martin IN EFI_SYSTEM_TABLE *SystemTable 49381f2915669f734f34e3e83c83287e7371e298390Olivier Martin ) 49481f2915669f734f34e3e83c83287e7371e298390Olivier Martin{ 49581f2915669f734f34e3e83c83287e7371e298390Olivier Martin return gBS->InstallProtocolInterface ( 49681f2915669f734f34e3e83c83287e7371e298390Olivier Martin &ImageHandle, 49781f2915669f734f34e3e83c83287e7371e298390Olivier Martin &gAndroidFastbootPlatformProtocolGuid, 49881f2915669f734f34e3e83c83287e7371e298390Olivier Martin EFI_NATIVE_INTERFACE, 49981f2915669f734f34e3e83c83287e7371e298390Olivier Martin &mPlatformProtocol 50081f2915669f734f34e3e83c83287e7371e298390Olivier Martin ); 50181f2915669f734f34e3e83c83287e7371e298390Olivier Martin} 502