Platforms/HiKey: update fastboot driver
Since sparse image is already implemented in AndroidFastbootApp, update
the HiKeyFastbootDxe driver too.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
diff --git a/Platforms/Hisilicon/HiKey/HiKey.dsc b/Platforms/Hisilicon/HiKey/HiKey.dsc
index 0413599..98353d8 100644
--- a/Platforms/Hisilicon/HiKey/HiKey.dsc
+++ b/Platforms/Hisilicon/HiKey/HiKey.dsc
@@ -60,6 +60,7 @@
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+ AbootimgLib|EmbeddedPkg/Library/AbootimgLib/AbootimgLib.inf
FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf
UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
PlatformBootManagerLib|OpenPlatformPkg/Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
diff --git a/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c
index 568c08b..d1ae898 100644
--- a/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c
+++ b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c
@@ -36,33 +36,18 @@
#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 BOOTIMG_KERNEL_ARGS_SIZE 1024
+#define PARTITION_NAME_MAX_LENGTH (72/2)
typedef struct _FASTBOOT_PARTITION_LIST {
LIST_ENTRY Link;
CHAR16 PartitionName[PARTITION_NAME_MAX_LENGTH];
- EFI_HANDLE PartitionHandle;
- EFI_LBA Lba;
+ EFI_LBA StartingLBA;
+ EFI_LBA EndingLBA;
} FASTBOOT_PARTITION_LIST;
-STATIC LIST_ENTRY mPartitionListHead;
-
+STATIC LIST_ENTRY mPartitionListHead;
+STATIC EFI_HANDLE mFlashHandle;
+STATIC EFI_BLOCK_IO_PROTOCOL *mFlashBlockIo;
STATIC EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *mTextOut;
/*
@@ -87,6 +72,7 @@
Entry = NextEntry;
}
}
+
/*
Read the PartitionName fields from the GPT partition entries, putting them
into an allocated array that should later be freed.
@@ -95,88 +81,86 @@
EFI_STATUS
ReadPartitionEntries (
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
- OUT EFI_PARTITION_ENTRY **PartitionEntries
+ OUT EFI_PARTITION_ENTRY **PartitionEntries,
+ OUT UINTN *PartitionNumbers
)
{
- UINTN EntrySize;
- UINTN NumEntries;
- UINTN BufferSize;
- UINT32 MediaId;
- EFI_PARTITION_TABLE_HEADER *GptHeader;
EFI_STATUS Status;
+ UINT32 MediaId;
+ UINTN BlockSize;
+ UINTN PageCount;
+ UINTN Count, EndLBA;
+ EFI_PARTITION_TABLE_HEADER *GptHeader;
+ EFI_PARTITION_ENTRY *Entry;
+ VOID *Buffer;
+
+ if ((PartitionEntries == NULL) || (PartitionNumbers == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
MediaId = BlockIo->Media->MediaId;
+ BlockSize = BlockIo->Media->BlockSize;
//
// Read size of Partition entry and number of entries from GPT header
//
- GptHeader = AllocatePool (BlockIo->Media->BlockSize);
- if (GptHeader == NULL) {
+ PageCount = EFI_SIZE_TO_PAGES (34 * BlockSize);
+ Buffer = AllocatePages (PageCount);
+ if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
- Status = BlockIo->ReadBlocks (BlockIo, MediaId, 1, BlockIo->Media->BlockSize, (VOID *) GptHeader);
+ Status = BlockIo->ReadBlocks (BlockIo, MediaId, 0, PageCount * EFI_PAGE_SIZE, Buffer);
if (EFI_ERROR (Status)) {
return Status;
}
+ GptHeader = (EFI_PARTITION_TABLE_HEADER *)(Buffer + BlockSize);
// Check there is a GPT on the media
if (GptHeader->Header.Signature != EFI_PTAB_HEADER_ID ||
GptHeader->MyLBA != 1) {
- DEBUG ((DEBUG_ERROR,
+ DEBUG ((EFI_D_ERROR,
"Fastboot platform: No GPT on flash. "
"Fastboot on Versatile Express 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;
+ Entry = (EFI_PARTITION_ENTRY *)(Buffer + (2 * BlockSize));
+ EndLBA = GptHeader->FirstUsableLBA - 1;
+ Count = 0;
+ while (1) {
+ if ((Entry->StartingLBA > EndLBA) && (Entry->EndingLBA <= GptHeader->LastUsableLBA)) {
+ Count++;
+ EndLBA = Entry->EndingLBA;
+ Entry++;
+ } else {
+ break;
+ }
+ }
+ if (Count == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Count > GptHeader->NumberOfPartitionEntries) {
+ Count = GptHeader->NumberOfPartitionEntries;
}
- Status = BlockIo->ReadBlocks (BlockIo, MediaId, 2, BufferSize, (VOID *) *PartitionEntries);
- if (EFI_ERROR (Status)) {
- FreePool (PartitionEntries);
- return Status;
- }
-
- return Status;
+ *PartitionEntries = (EFI_PARTITION_ENTRY *)((UINTN)Buffer + (2 * BlockSize));
+ *PartitionNumbers = Count;
+ return EFI_SUCCESS;
}
-
-/*
- 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.
-*/
EFI_STATUS
-HiKeyFastbootPlatformInit (
+LoadPtable (
VOID
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *FlashDevicePath;
EFI_DEVICE_PATH_PROTOCOL *FlashDevicePathDup;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_DEVICE_PATH_PROTOCOL *NextNode;
- HARDDRIVE_DEVICE_PATH *PartitionNode;
- UINTN NumHandles;
- EFI_HANDLE *AllHandles;
+ UINTN PartitionNumbers;
UINTN LoopIndex;
- EFI_HANDLE FlashHandle;
- EFI_BLOCK_IO_PROTOCOL *FlashBlockIo;
EFI_PARTITION_ENTRY *PartitionEntries;
FASTBOOT_PARTITION_LIST *Entry;
@@ -197,26 +181,22 @@
// 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);
+ Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &FlashDevicePathDup, &mFlashHandle);
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,
+ mFlashHandle,
&gEfiBlockIoProtocolGuid,
- (VOID **) &FlashBlockIo,
+ (VOID **) &mFlashBlockIo,
gImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
@@ -227,115 +207,49 @@
}
// Read the GPT partition entry array into memory so we can get the partition names
- Status = ReadPartitionEntries (FlashBlockIo, &PartitionEntries);
+ Status = ReadPartitionEntries (mFlashBlockIo, &PartitionEntries, &PartitionNumbers);
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);
-
- // Check if it is a sub-device of the flash device
- if (!CompareMem (DevicePath, FlashDevicePath, FLASH_DEVICE_PATH_SIZE (FlashDevicePath))) {
- // Device path starts with path of flash device. Check it isn't the flash
- // device itself.
- NextNode = NextDevicePathNode (DevicePath);
- if (IsDevicePathEndType (NextNode)) {
- // Create entry
- Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST));
- if (Entry == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- FreePartitionList ();
- goto Exit;
- }
-
- // Copy handle and partition name
- Entry->PartitionHandle = AllHandles[LoopIndex];
- StrCpy (Entry->PartitionName, L"ptable");
- InsertTailList (&mPartitionListHead, &Entry->Link);
- continue;
- }
-
- // Assert that this device path node represents a partition.
- ASSERT (NextNode->Type == MEDIA_DEVICE_PATH &&
- NextNode->SubType == MEDIA_HARDDRIVE_DP);
-
- PartitionNode = (HARDDRIVE_DEVICE_PATH *) NextNode;
-
- // Assert that the partition type is GPT. ReadPartitionEntries checks for
- // presence of a GPT, so we should never find MBR partitions.
- // ("MBRType" is a misnomer - this field is actually called "Partition
- // Format")
- ASSERT (PartitionNode->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER);
-
- // The firmware may install a handle for "partition 0", representing the
- // whole device. Ignore it.
- if (PartitionNode->PartitionNumber == 0) {
- continue;
- }
-
- //
- // Add the partition handle to the list
- //
-
- // Create entry
- Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST));
- if (Entry == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- FreePartitionList ();
- goto Exit;
- }
-
- // Copy handle and partition name
- Entry->PartitionHandle = AllHandles[LoopIndex];
- StrnCpy (
- Entry->PartitionName,
- PartitionEntries[PartitionNode->PartitionNumber - 1].PartitionName, // Partition numbers start from 1.
- PARTITION_NAME_MAX_LENGTH
- );
- 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_ERROR,
- "Warning: Partition %d doesn't seem to have a GPT partition label. "
- "You won't be able to flash it with Fastboot.\n",
- PartitionNode->PartitionNumber
- ));
- }
+ for (LoopIndex = 0; LoopIndex < PartitionNumbers; LoopIndex++) {
+ // Create entry
+ Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST));
+ if (Entry == NULL) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ FreePartitionList ();
+ goto Exit;
}
+ StrnCpy (
+ Entry->PartitionName,
+ PartitionEntries[LoopIndex].PartitionName,
+ PARTITION_NAME_MAX_LENGTH
+ );
+ Entry->StartingLBA = PartitionEntries[LoopIndex].StartingLBA;
+ Entry->EndingLBA = PartitionEntries[LoopIndex].EndingLBA;
+ InsertTailList (&mPartitionListHead, &Entry->Link);
}
-
Exit:
- FreePool (PartitionEntries);
- FreePool (FlashDevicePath);
- FreePool (AllHandles);
+ FreePages (
+ (VOID *)((UINTN)PartitionEntries - (2 * mFlashBlockIo->Media->BlockSize)),
+ EFI_SIZE_TO_PAGES (34 * mFlashBlockIo->Media->BlockSize)
+ );
return Status;
+}
+/*
+ Initialise: Open the Android NVM device and find the partitions on it. Save them in
+ a list along with the "PartitionName" fields for their GPT entries.
+ We will use these partition names as the key in
+ HiKeyFastbootPlatformFlashPartition.
+*/
+EFI_STATUS
+HiKeyFastbootPlatformInit (
+ VOID
+ )
+{
+ return LoadPtable ();
}
VOID
@@ -347,6 +261,87 @@
}
EFI_STATUS
+HiKeyFlashPtable (
+ IN UINTN Size,
+ IN VOID *Image
+ )
+{
+ EFI_STATUS Status;
+ VOID *Buffer;
+ UINTN BlockSize;
+ EFI_DISK_IO_PROTOCOL *DiskIo;
+ UINT32 EntrySize, EntryOffset;
+ UINT32 MediaId;
+
+ MediaId = mFlashBlockIo->Media->MediaId;
+ BlockSize = mFlashBlockIo->Media->BlockSize;
+ Status = gBS->OpenProtocol (
+ mFlashHandle,
+ &gEfiDiskIoProtocolGuid,
+ (VOID **) &DiskIo,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Buffer = Image;
+ if (AsciiStrnCmp (Buffer, "ENTRYHDR", 8) != 0) {
+ DEBUG ((EFI_D_ERROR, "unknown ptable image\n"));
+ return EFI_UNSUPPORTED;
+ }
+ Buffer += 8;
+ if (AsciiStrnCmp (Buffer, "primary", 7) != 0) {
+ DEBUG ((EFI_D_ERROR, "unknown ptable imag\n"));
+ return EFI_UNSUPPORTED;
+ }
+ Buffer += 8;
+ EntryOffset = *(UINT32 *)Buffer * BlockSize;
+ Buffer += 4;
+ EntrySize = *(UINT32 *)Buffer * BlockSize;
+ if ((EntrySize + BlockSize) > Size) {
+ DEBUG ((DEBUG_ERROR, "Entry size doesn't match\n"));
+ return EFI_UNSUPPORTED;
+ }
+ Buffer = Image + BlockSize;
+ Status = DiskIo->WriteDisk (DiskIo, MediaId, EntryOffset, EntrySize, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ FreePartitionList ();
+ Status = LoadPtable ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Buffer = Image + 16 + 12;
+ if (AsciiStrnCmp (Buffer, "ENTRYHDR", 8) != 0) {
+ return Status;
+ }
+ Buffer += 8;
+ if (AsciiStrnCmp (Buffer, "second", 6) != 0) {
+ return Status;
+ }
+ Buffer += 8;
+ EntryOffset = *(UINT32 *)Buffer * BlockSize;
+ Buffer += 4;
+ EntrySize = *(UINT32 *)Buffer * BlockSize;
+ if ((EntrySize + BlockSize) > Size) {
+ DEBUG ((DEBUG_ERROR, "Entry size doens't match\n"));
+ return EFI_UNSUPPORTED;
+ }
+ Buffer = Image + BlockSize;
+ Status = DiskIo->WriteDisk (DiskIo, MediaId, EntryOffset, EntrySize, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ mFlashBlockIo->FlushBlocks (mFlashBlockIo);
+ MicroSecondDelay (50000);
+ return Status;
+}
+
+EFI_STATUS
HiKeyFastbootPlatformFlashPartition (
IN CHAR8 *PartitionName,
IN UINTN Size,
@@ -354,27 +349,19 @@
)
{
EFI_STATUS Status;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
- EFI_DISK_IO_PROTOCOL *DiskIo;
- UINT32 MediaId;
UINTN PartitionSize;
FASTBOOT_PARTITION_LIST *Entry;
CHAR16 PartitionNameUnicode[60];
BOOLEAN PartitionFound;
-#ifdef SPARSE_HEADER
- SPARSE_HEADER *SparseHeader;
- CHUNK_HEADER *ChunkHeader;
- UINTN Offset = 0;
- UINT32 Chunk, EntrySize, EntryOffset;
- UINT32 *FillVal, TmpCount, FillBuf[1024];
-#else
- UINT32 EntrySize, EntryOffset;
-#endif
- VOID *Buffer;
+ EFI_DISK_IO_PROTOCOL *DiskIo;
+ UINTN BlockSize;
+ // Support the pseudo partition name, such as "ptable".
+ if (AsciiStrCmp (PartitionName, "ptable") == 0) {
+ return HiKeyFlashPtable (Size, Image);
+ }
AsciiStrToUnicodeStr (PartitionName, PartitionNameUnicode);
-
PartitionFound = FALSE;
Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead));
while (!IsNull (&mPartitionListHead, &Entry->Link)) {
@@ -390,50 +377,17 @@
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;
- }
-
-#ifdef SPARSE_HEADER
- SparseHeader=(SPARSE_HEADER *)Image;
-
- if (SparseHeader->Magic == SPARSE_HEADER_MAGIC) {
- DEBUG ((DEBUG_INFO, "Sparse Magic: 0x%x Major: %d Minor: %d fhs: %d chs: %d bs: %d tbs: %d tcs: %d checksum: %d \n",
- SparseHeader->Magic, SparseHeader->MajorVersion, SparseHeader->MinorVersion, SparseHeader->FileHeaderSize,
- SparseHeader->ChunkHeaderSize, SparseHeader->BlockSize, SparseHeader->TotalBlocks,
- SparseHeader->TotalChunks, SparseHeader->ImageChecksum));
- if (SparseHeader->MajorVersion != 1) {
- DEBUG ((DEBUG_ERROR, "Sparse image version %d.%d not supported.\n",
- SparseHeader->MajorVersion, SparseHeader->MinorVersion));
- return EFI_INVALID_PARAMETER;
- }
-
- Size = SparseHeader->BlockSize * SparseHeader->TotalBlocks;
- }
-#endif
-
// Check image will fit on device
- PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize;
+ BlockSize = mFlashBlockIo->Media->BlockSize;
+ PartitionSize = (Entry->EndingLBA - Entry->StartingLBA + 1) * 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,
+ mFlashHandle,
&gEfiDiskIoProtocolGuid,
(VOID **) &DiskIo,
gImageHandle,
@@ -442,144 +396,111 @@
);
ASSERT_EFI_ERROR (Status);
-#ifdef SPARSE_HEADER
- if (SparseHeader->Magic == SPARSE_HEADER_MAGIC) {
- CHAR16 OutputString[64];
- UINTN ChunkPrintDensity =
- SparseHeader->TotalChunks > 1600 ? SparseHeader->TotalChunks / 200 : 32;
-
- Image += SparseHeader->FileHeaderSize;
- for (Chunk = 0; Chunk < SparseHeader->TotalChunks; Chunk++) {
- UINTN WriteSize;
- ChunkHeader = (CHUNK_HEADER *)Image;
-
- // Show progress. Don't do it for every packet as outputting text
- // might be time consuming. ChunkPrintDensity is calculated to
- // provide an update every half percent change for large
- // downloads.
- if (Chunk % ChunkPrintDensity == 0) {
- UnicodeSPrint(OutputString, sizeof(OutputString),
- L"\r%5d / %5d chunks written (%d%%)", Chunk,
- SparseHeader->TotalChunks,
- (Chunk * 100) / SparseHeader->TotalChunks);
- mTextOut->OutputString(mTextOut, OutputString);
- }
-
- DEBUG ((DEBUG_INFO, "Chunk #%d - Type: 0x%x Size: %d TotalSize: %d Offset %d\n",
- (Chunk+1), ChunkHeader->ChunkType, ChunkHeader->ChunkSize,
- ChunkHeader->TotalSize, Offset));
- Image += sizeof(CHUNK_HEADER);
- WriteSize=(SparseHeader->BlockSize) * ChunkHeader->ChunkSize;
- switch (ChunkHeader->ChunkType) {
- case CHUNK_TYPE_RAW:
- DEBUG ((DEBUG_INFO, "Writing %d at Offset %d\n", WriteSize, Offset));
- Status = DiskIo->WriteDisk (DiskIo, MediaId, Offset, WriteSize, Image);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Image+=WriteSize;
- break;
- case CHUNK_TYPE_FILL:
- //Assume fillVal is 0, and we can skip here
- FillVal = (UINT32 *)Image;
- Image += sizeof(UINT32);
- if (*FillVal != 0){
- mTextOut->OutputString(mTextOut, OutputString);
- for(TmpCount = 0; TmpCount < 1024; TmpCount++){
- FillBuf[TmpCount] = *FillVal;
- }
- for (TmpCount= 0; TmpCount < WriteSize; TmpCount += sizeof(FillBuf)) {
- if ((WriteSize - TmpCount) < sizeof(FillBuf)) {
- Status = DiskIo->WriteDisk (DiskIo, MediaId, Offset + TmpCount, WriteSize - TmpCount, FillBuf);
- } else {
- Status = DiskIo->WriteDisk (DiskIo, MediaId, Offset + TmpCount, sizeof(FillBuf), FillBuf);
- }
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
- }
- break;
- case CHUNK_TYPE_DONT_CARE:
- break;
- case CHUNK_TYPE_CRC32:
- break;
- default:
- DEBUG ((DEBUG_ERROR, "Unknown Chunk Type: 0x%x", ChunkHeader->ChunkType));
- return EFI_PROTOCOL_ERROR;
- }
- Offset += WriteSize;
- }
-
- UnicodeSPrint(OutputString, sizeof(OutputString),
- L"\r%5d / %5d chunks written (100%%)\r\n",
- SparseHeader->TotalChunks, SparseHeader->TotalChunks);
- mTextOut->OutputString(mTextOut, OutputString);
- } else {
-#endif
- if (AsciiStrCmp (PartitionName, "ptable") == 0) {
- Buffer = Image;
- if (AsciiStrnCmp (Buffer, "ENTRYHDR", 8) != 0) {
- DEBUG ((DEBUG_ERROR, "unknown ptable image\n"));
- return EFI_UNSUPPORTED;
- }
- Buffer += 8;
- if (AsciiStrnCmp (Buffer, "primary", 7) != 0) {
- DEBUG ((DEBUG_ERROR, "unknown ptable image\n"));
- return EFI_UNSUPPORTED;
- }
- Buffer += 8;
- EntryOffset = *(UINT32 *)Buffer * BlockIo->Media->BlockSize;
- Buffer += 4;
- EntrySize = *(UINT32 *)Buffer * BlockIo->Media->BlockSize;
- if ((EntrySize + 512) > Size) {
- DEBUG ((DEBUG_ERROR, "Entry size doesn't match\n"));
- return EFI_UNSUPPORTED;
- }
- Buffer = Image + 512;
- Status = DiskIo->WriteDisk (DiskIo, MediaId, EntryOffset, EntrySize, Buffer);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Buffer = Image + 16 + 12;
- if (AsciiStrnCmp (Buffer, "ENTRYHDR", 8) != 0)
- return Status;
- Buffer += 8;
- if (AsciiStrnCmp (Buffer, "second", 6) != 0)
- return Status;
- Buffer += 8;
- EntryOffset = *(UINT32 *)Buffer * BlockIo->Media->BlockSize;
- Buffer += 4;
- EntrySize = *(UINT32 *)Buffer * BlockIo->Media->BlockSize;
- if ((EntrySize + 512) > Size) {
- DEBUG ((DEBUG_ERROR, "Entry size doesn't match\n"));
- return EFI_UNSUPPORTED;
- }
- Buffer = Image + 512;
- Status = DiskIo->WriteDisk (DiskIo, MediaId, EntryOffset, EntrySize, Buffer);
- } else {
- Status = DiskIo->WriteDisk (DiskIo, MediaId, 0, Size, Image);
- }
- if (EFI_ERROR (Status)) {
- return Status;
- }
-#ifdef SPARSE_HEADER
+ Status = DiskIo->WriteDisk (
+ DiskIo,
+ mFlashBlockIo->Media->MediaId,
+ Entry->StartingLBA * BlockSize,
+ Size,
+ Image
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to write %d bytes into 0x%x, Status:%r\n", Size, Entry->StartingLBA * BlockSize, Status));
+ return Status;
}
-#endif
- BlockIo->FlushBlocks(BlockIo);
+ mFlashBlockIo->FlushBlocks(mFlashBlockIo);
MicroSecondDelay (50000);
return Status;
}
EFI_STATUS
+HiKeyErasePtable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_ERASE_BLOCK_PROTOCOL *EraseBlockProtocol;
+
+ Status = gBS->OpenProtocol (
+ mFlashHandle,
+ &gEfiEraseBlockProtocolGuid,
+ (VOID **) &EraseBlockProtocol,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fastboot platform: could not open Erase Block IO: %r\n", Status));
+ return EFI_DEVICE_ERROR;
+ }
+ Status = EraseBlockProtocol->EraseBlocks (
+ EraseBlockProtocol,
+ mFlashBlockIo->Media->MediaId,
+ 0,
+ NULL,
+ 34 * mFlashBlockIo->Media->BlockSize
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ FreePartitionList ();
+ return Status;
+}
+
+EFI_STATUS
HiKeyFastbootPlatformErasePartition (
IN CHAR8 *PartitionName
)
{
- return EFI_SUCCESS;
+ EFI_STATUS Status;
+ EFI_ERASE_BLOCK_PROTOCOL *EraseBlockProtocol;
+ UINTN Size;
+ BOOLEAN PartitionFound;
+ CHAR16 PartitionNameUnicode[60];
+ FASTBOOT_PARTITION_LIST *Entry;
+
+ AsciiStrToUnicodeStr (PartitionName, PartitionNameUnicode);
+
+ // Support the pseudo partition name, such as "ptable".
+ if (AsciiStrCmp (PartitionName, "ptable") == 0) {
+ return HiKeyErasePtable ();
+ }
+
+ 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 (
+ mFlashHandle,
+ &gEfiEraseBlockProtocolGuid,
+ (VOID **) &EraseBlockProtocol,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Size = (Entry->EndingLBA - Entry->StartingLBA + 1) * mFlashBlockIo->Media->BlockSize;
+ Status = EraseBlockProtocol->EraseBlocks (
+ EraseBlockProtocol,
+ mFlashBlockIo->Media->MediaId,
+ Entry->StartingLBA,
+ NULL,
+ Size
+ );
+ return Status;
}
EFI_STATUS
@@ -589,7 +510,6 @@
)
{
EFI_STATUS Status;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
UINT64 PartitionSize;
FASTBOOT_PARTITION_LIST *Entry;
CHAR16 PartitionNameUnicode[60];
@@ -634,25 +554,11 @@
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;
- }
-
- PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize;
- DEBUG ((DEBUG_ERROR, "Fastboot platform: check for partition-size:%a 0X%llx\n", Name, PartitionSize ));
+ PartitionSize = (Entry->EndingLBA - Entry->StartingLBA + 1) * mFlashBlockIo->Media->BlockSize;
+ DEBUG ((DEBUG_ERROR, "Fastboot platform: check for partition-size:%a 0X%llx\n", Name, PartitionSize));
AsciiSPrint (Value, 12, "0x%llx", PartitionSize);
} else if ( !AsciiStrnCmp (Name, "partition-type", 14)) {
- DEBUG ((DEBUG_ERROR, "Fastboot platform: check for partition-type:%a\n", (Name + 15) ));
+ DEBUG ((DEBUG_ERROR, "Fastboot platform: check for partition-type:%a\n", (Name + 15)));
if ( !AsciiStrnCmp ( (Name + 15) , "system", 6) || !AsciiStrnCmp ( (Name + 15) , "userdata", 8)
|| !AsciiStrnCmp ( (Name + 15) , "cache", 5)) {
AsciiStrCpy (Value, "ext4");
@@ -682,22 +588,72 @@
}
}
-CHAR16 *
-HiKeyFastbootPlatformGetKernelArgs (
- VOID
+EFI_STATUS
+HiKeyFastbootPlatformFlashPartitionEx (
+ IN CHAR8 *PartitionName,
+ IN UINTN Offset,
+ IN UINTN Size,
+ IN VOID *Image
)
{
- CHAR16 *CommandLineArgs;
+ EFI_STATUS Status;
+ UINTN PartitionSize;
+ FASTBOOT_PARTITION_LIST *Entry;
+ CHAR16 PartitionNameUnicode[60];
+ BOOLEAN PartitionFound;
+ UINTN BlockSize;
+ EFI_DISK_IO_PROTOCOL *DiskIo;
- CommandLineArgs = AllocateZeroPool (BOOTIMG_KERNEL_ARGS_SIZE);
- if (CommandLineArgs == NULL) {
- return NULL;
+ 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);
}
- UnicodeSPrint (
- CommandLineArgs, BOOTIMG_KERNEL_ARGS_SIZE,
- L"root=/dev/mmcblk0p9 earlycon=pl011,0xf7113000"
- );
- return CommandLineArgs;
+ if (!PartitionFound) {
+ return EFI_NOT_FOUND;
+ }
+
+ // Check image will fit on device
+ PartitionSize = (Entry->EndingLBA - Entry->StartingLBA + 1) * mFlashBlockIo->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;
+ }
+
+ BlockSize = mFlashBlockIo->Media->BlockSize;
+ Status = gBS->OpenProtocol (
+ mFlashHandle,
+ &gEfiDiskIoProtocolGuid,
+ (VOID **) &DiskIo,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = DiskIo->WriteDisk (
+ DiskIo,
+ mFlashBlockIo->Media->MediaId,
+ Entry->StartingLBA * BlockSize + Offset,
+ Size,
+ Image
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to write %d bytes into 0x%x, Status:%r\n", Size, Entry->StartingLBA * BlockSize + Offset, Status));
+ return Status;
+ }
+ return Status;
}
FASTBOOT_PLATFORM_PROTOCOL mPlatformProtocol = {
@@ -707,7 +663,7 @@
HiKeyFastbootPlatformErasePartition,
HiKeyFastbootPlatformGetVar,
HiKeyFastbootPlatformOemCommand,
- HiKeyFastbootPlatformGetKernelArgs
+ HiKeyFastbootPlatformFlashPartitionEx
};
EFI_STATUS