* [PATCH] EmbeddedPkg/AndroidFastbootApp: support sparse image
@ 2017-04-14 9:55 Haojian Zhuang
2017-05-04 10:48 ` Leif Lindholm
0 siblings, 1 reply; 4+ messages in thread
From: Haojian Zhuang @ 2017-04-14 9:55 UTC (permalink / raw)
To: leif.lindholm, ard.biesheuvel, edk2-devel; +Cc: Haojian Zhuang
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 | 127 +++++++++++++++++++--
.../Include/Protocol/AndroidFastbootPlatform.h | 23 ++++
2 files changed, 142 insertions(+), 8 deletions(-)
diff --git a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c
index 61abc67..4883a77 100644
--- a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c
+++ b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c
@@ -25,7 +25,34 @@
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
-#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;
/*
* UEFI Application using the FASTBOOT_TRANSPORT_PROTOCOL and
@@ -139,13 +166,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, FILL_BUF_SIZE * sizeof (UINT32), *(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);
@@ -157,11 +254,25 @@ 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");
diff --git a/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h b/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h
index a9b4aac..2cb51eb 100644
--- a/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h
+++ b/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h
@@ -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
--
2.7.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] EmbeddedPkg/AndroidFastbootApp: support sparse image
2017-04-14 9:55 [PATCH] EmbeddedPkg/AndroidFastbootApp: support sparse image Haojian Zhuang
@ 2017-05-04 10:48 ` Leif Lindholm
2017-05-11 7:27 ` Haojian Zhuang
0 siblings, 1 reply; 4+ messages in thread
From: Leif Lindholm @ 2017-05-04 10:48 UTC (permalink / raw)
To: Haojian Zhuang; +Cc: ard.biesheuvel, edk2-devel
On Fri, Apr 14, 2017 at 05:55:32PM +0800, Haojian Zhuang wrote:
> 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 | 127 +++++++++++++++++++--
> .../Include/Protocol/AndroidFastbootPlatform.h | 23 ++++
> 2 files changed, 142 insertions(+), 8 deletions(-)
>
> diff --git a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c
> index 61abc67..4883a77 100644
> --- a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c
> +++ b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c
> @@ -25,7 +25,34 @@
> #include <Library/UefiBootServicesTableLib.h>
> #include <Library/UefiRuntimeServicesTableLib.h>
>
> -#define ANDROID_FASTBOOT_VERSION "0.4"
> +#define ANDROID_FASTBOOT_VERSION "0.5"
Could this #define, as well as the ones below, and the typedefs, and
the macros, all be moved into AndroidFastbootApp.h?
Actually, I'm confused. In current upstream EDK2, this #define _is_ in
AndroidFastbootApp.h. What is this patch against?
> +
> +#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
Is this meeting some specification limit, or an arbitrary value?
> +
> +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;
>
> /*
> * UEFI Application using the FASTBOOT_TRANSPORT_PROTOCOL and
> @@ -139,13 +166,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, FILL_BUF_SIZE * sizeof (UINT32), *(UINT32 *)Image);
It's in scope, "sizeof (FillBuf)" would be more clear (and less error prone).
> + 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);
> @@ -157,11 +254,25 @@ 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",
Indent is two spaces.
> + SparseHeader->MajorVersion, SparseHeader->MinorVersion));
These indents (two DEBUG statements above) look a bit funky.
Should the continuation lines not line up with DEBUG_?
/
Leif
> + 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");
> diff --git a/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h b/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h
> index a9b4aac..2cb51eb 100644
> --- a/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h
> +++ b/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h
> @@ -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
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] EmbeddedPkg/AndroidFastbootApp: support sparse image
2017-05-04 10:48 ` Leif Lindholm
@ 2017-05-11 7:27 ` Haojian Zhuang
0 siblings, 0 replies; 4+ messages in thread
From: Haojian Zhuang @ 2017-05-11 7:27 UTC (permalink / raw)
To: Leif Lindholm; +Cc: ard.biesheuvel, edk2-devel
On 2017/5/4 18:48, Leif Lindholm wrote:
> On Fri, Apr 14, 2017 at 05:55:32PM +0800, Haojian Zhuang wrote:
>> 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 | 127 +++++++++++++++++++--
>> .../Include/Protocol/AndroidFastbootPlatform.h | 23 ++++
>> 2 files changed, 142 insertions(+), 8 deletions(-)
>>
>> diff --git a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c
>> index 61abc67..4883a77 100644
>> --- a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c
>> +++ b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c
>> @@ -25,7 +25,34 @@
>> #include <Library/UefiBootServicesTableLib.h>
>> #include <Library/UefiRuntimeServicesTableLib.h>
>>
>> -#define ANDROID_FASTBOOT_VERSION "0.4"
>> +#define ANDROID_FASTBOOT_VERSION "0.5"
>
> Could this #define, as well as the ones below, and the typedefs, and
> the macros, all be moved into AndroidFastbootApp.h?
>
> Actually, I'm confused. In current upstream EDK2, this #define _is_ in
> AndroidFastbootApp.h. What is this patch against?
>
Maybe the EDK2 that I'm using is out of date. I'll sync to the latest one.
>> +
>> +#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
>
> Is this meeting some specification limit, or an arbitrary value?
>
Yes, it's defined by android sparse image. Here's the reference
(http://www.2net.co.uk/tutorial/android-sparse-image-format).
The image is split into chunks of multiples of 4096 bytes.
1024 * sizeof (UINT32) = 4096 bytes
>> +
>> +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;
>>
>> /*
>> * UEFI Application using the FASTBOOT_TRANSPORT_PROTOCOL and
>> @@ -139,13 +166,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, FILL_BUF_SIZE * sizeof (UINT32), *(UINT32 *)Image);
>
> It's in scope, "sizeof (FillBuf)" would be more clear (and less error prone).
>
OK
>> + 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);
>> @@ -157,11 +254,25 @@ 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",
>
> Indent is two spaces.
>
OK
>> + SparseHeader->MajorVersion, SparseHeader->MinorVersion));
>
> These indents (two DEBUG statements above) look a bit funky.
> Should the continuation lines not line up with DEBUG_?
>
> /
> Leif
>
>> + 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");
>> diff --git a/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h b/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h
>> index a9b4aac..2cb51eb 100644
>> --- a/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h
>> +++ b/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h
>> @@ -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
>> --
>> 2.7.4
>>
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] EmbeddedPkg/AndroidFastbootApp: support sparse image
2017-05-12 3:46 [PATCH v2] support sparse image in AndroidFastbootApp Haojian Zhuang
@ 2017-05-12 3:46 ` Haojian Zhuang
0 siblings, 0 replies; 4+ messages in thread
From: Haojian Zhuang @ 2017-05-12 3:46 UTC (permalink / raw)
To: leif.lindholm, ard.biesheuvel, edk2-devel; +Cc: Haojian Zhuang
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(-)
diff --git a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c
index c5e8a7e..6226bd5 100644
--- a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c
+++ b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c
@@ -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");
diff --git a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.h b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.h
index f62660f..0e90b1f 100644
--- a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.h
+++ b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.h
@@ -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 (
diff --git a/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h b/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h
index a9b4aac..2cb51eb 100644
--- a/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h
+++ b/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h
@@ -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
--
2.7.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2017-05-12 3:46 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-04-14 9:55 [PATCH] EmbeddedPkg/AndroidFastbootApp: support sparse image Haojian Zhuang
2017-05-04 10:48 ` Leif Lindholm
2017-05-11 7:27 ` Haojian Zhuang
-- strict thread matches above, loose matches on Subject: below --
2017-05-12 3:46 [PATCH v2] support sparse image in AndroidFastbootApp Haojian Zhuang
2017-05-12 3:46 ` [PATCH] EmbeddedPkg/AndroidFastbootApp: support sparse image Haojian Zhuang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox