@@ -138,13 +138,83 @@ HandleDownload (
}
STATIC
+EFI_STATUS
+FlashSparseImage (
+ IN CHAR8 *PartitionName,
+ IN SPARSE_HEADER *SparseHeader
+ )
+{
+ EFI_STATUS Status;
+ UINTN Chunk, Offset = 0, Index;
+ VOID *Image;
+ CHUNK_HEADER *ChunkHeader;
+ UINT32 FillBuf[FILL_BUF_SIZE];
+ CHAR16 OutputString[FASTBOOT_STRING_MAX_LENGTH];
+
+ Image = (VOID *)SparseHeader;
+ Image += SparseHeader->FileHeaderSize;
+ for (Chunk = 0; Chunk < SparseHeader->TotalChunks; Chunk++) {
+ ChunkHeader = (CHUNK_HEADER *)Image;
+ 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);
+ switch (ChunkHeader->ChunkType) {
+ case CHUNK_TYPE_RAW:
+ Status = mPlatform->FlashPartitionEx (
+ PartitionName,
+ Offset,
+ ChunkHeader->ChunkSize * SparseHeader->BlockSize,
+ Image
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Image += ChunkHeader->ChunkSize * SparseHeader->BlockSize;
+ Offset += ChunkHeader->ChunkSize * SparseHeader->BlockSize;
+ break;
+ case CHUNK_TYPE_FILL:
+ SetMem32 (FillBuf, sizeof (FillBuf), *(UINT32 *)Image);
+ Image += sizeof (UINT32);
+ for (Index = 0; Index < ChunkHeader->ChunkSize; Index++) {
+ Status = mPlatform->FlashPartitionEx (
+ PartitionName,
+ Offset,
+ SparseHeader->BlockSize,
+ FillBuf
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Offset += SparseHeader->BlockSize;
+ }
+ break;
+ case CHUNK_TYPE_DONT_CARE:
+ Offset += ChunkHeader->ChunkSize * SparseHeader->BlockSize;
+ break;
+ default:
+ UnicodeSPrint (
+ OutputString,
+ sizeof (OutputString),
+ L"Unsupported Chunk Type:0x%x\n",
+ ChunkHeader->ChunkType
+ );
+ mTextOut->OutputString (mTextOut, OutputString);
+ break;
+ }
+ }
+ return Status;
+}
+
+STATIC
VOID
HandleFlash (
IN CHAR8 *PartitionName
)
{
- EFI_STATUS Status;
- CHAR16 OutputString[FASTBOOT_STRING_MAX_LENGTH];
+ EFI_STATUS Status;
+ CHAR16 OutputString[FASTBOOT_STRING_MAX_LENGTH];
+ SPARSE_HEADER *SparseHeader;
// Build output string
UnicodeSPrint (OutputString, sizeof (OutputString), L"Flashing partition %a\r\n", PartitionName);
@@ -156,11 +226,27 @@ HandleFlash (
return;
}
- Status = mPlatform->FlashPartition (
- PartitionName,
- mNumDataBytes,
- mDataBuffer
- );
+ SparseHeader = (SPARSE_HEADER *)mDataBuffer;
+ 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;
+ }
+ Status = FlashSparseImage (PartitionName, SparseHeader);
+ } else {
+ Status = mPlatform->FlashPartition (
+ PartitionName,
+ mNumDataBytes,
+ mDataBuffer
+ );
+ }
if (Status == EFI_NOT_FOUND) {
SEND_LITERAL ("FAILNo such partition.");
mTextOut->OutputString (mTextOut, L"No such partition.\r\n");
@@ -21,7 +21,34 @@
#define BOOTIMG_KERNEL_ARGS_SIZE 512
-#define ANDROID_FASTBOOT_VERSION "0.4"
+#define ANDROID_FASTBOOT_VERSION "0.5"
+
+#define SPARSE_HEADER_MAGIC 0xED26FF3A
+#define CHUNK_TYPE_RAW 0xCAC1
+#define CHUNK_TYPE_FILL 0xCAC2
+#define CHUNK_TYPE_DONT_CARE 0xCAC3
+#define CHUNK_TYPE_CRC32 0xCAC4
+
+#define FILL_BUF_SIZE 1024
+
+typedef struct _SPARSE_HEADER {
+ UINT32 Magic;
+ UINT16 MajorVersion;
+ UINT16 MinorVersion;
+ UINT16 FileHeaderSize;
+ UINT16 ChunkHeaderSize;
+ UINT32 BlockSize;
+ UINT32 TotalBlocks;
+ UINT32 TotalChunks;
+ UINT32 ImageChecksum;
+} SPARSE_HEADER;
+
+typedef struct _CHUNK_HEADER {
+ UINT16 ChunkType;
+ UINT16 Reserved1;
+ UINT32 ChunkSize;
+ UINT32 TotalSize;
+} CHUNK_HEADER;
EFI_STATUS
BootAndroidBootImg (
@@ -133,6 +133,28 @@ EFI_STATUS
IN CHAR8 *Command
);
+/*
+ Flash the partition named (according to a platform-specific scheme)
+ PartitionName, with partition offset and the image pointed to by Buffer,
+ whose size is BufferSize.
+
+ @param[in] PartitionName Null-terminated name of partition to write.
+ @param[in] Offset Offset of partition.
+ @param[in] BufferSize Size of Buffer in byets.
+ @param[in] Buffer Data to write to partition.
+
+ @retval EFI_NOT_FOUND No such partition.
+ @retval EFI_DEVICE_ERROR Flashing failed.
+*/
+typedef
+EFI_STATUS
+(*FASTBOOT_PLATFORM_FLASH_EX) (
+ IN CHAR8 *PartitionName,
+ IN UINTN Offset,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
typedef struct _FASTBOOT_PLATFORM_PROTOCOL {
FASTBOOT_PLATFORM_INIT Init;
FASTBOOT_PLATFORM_UN_INIT UnInit;
@@ -140,6 +162,7 @@ typedef struct _FASTBOOT_PLATFORM_PROTOCOL {
FASTBOOT_PLATFORM_ERASE ErasePartition;
FASTBOOT_PLATFORM_GETVAR GetVar;
FASTBOOT_PLATFORM_OEM_COMMAND DoOemCommand;
+ FASTBOOT_PLATFORM_FLASH_EX FlashPartitionEx;
} FASTBOOT_PLATFORM_PROTOCOL;
#endif
Support sparse image that is reformatted from large raw image and splitted into a few smaller images. The sparse image follows the rule of Android Sparse Image format. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org> --- .../AndroidFastboot/AndroidFastbootApp.c | 100 +++++++++++++++++++-- .../AndroidFastboot/AndroidFastbootApp.h | 29 +++++- .../Include/Protocol/AndroidFastbootPlatform.h | 23 +++++ 3 files changed, 144 insertions(+), 8 deletions(-) -- 2.7.4 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel