[PATCH] fastboot: Add 'fastboot boot Image-dtb' support

Change-Id: Ib1bb01a2017cedccb3cab210f7c59b1d936c65f3
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
diff --git a/EmbeddedPkg/Application/AndroidFastboot/AndroidBootImg.c b/EmbeddedPkg/Application/AndroidFastboot/AndroidBootImg.c
index bbca90f..105a82f 100644
--- a/EmbeddedPkg/Application/AndroidFastboot/AndroidBootImg.c
+++ b/EmbeddedPkg/Application/AndroidFastboot/AndroidBootImg.c
@@ -14,32 +14,9 @@
 

 #include "AndroidFastbootApp.h"

 

-#define BOOT_MAGIC        "ANDROID!"

-#define BOOT_MAGIC_LENGTH sizeof (BOOT_MAGIC) - 1

-

 // Check Val (unsigned) is a power of 2 (has only one bit set)

 #define IS_POWER_OF_2(Val) (Val != 0 && ((Val & (Val - 1)) == 0))

 

-// No documentation for this really - sizes of fields has been determined

-// empirically.

-#pragma pack(1)

-typedef struct {

-  CHAR8   BootMagic[BOOT_MAGIC_LENGTH];

-  UINT32  KernelSize;

-  UINT32  KernelAddress;

-  UINT32  RamdiskSize;

-  UINT32  RamdiskAddress;

-  UINT32  SecondStageBootloaderSize;

-  UINT32  SecondStageBootloaderAddress;

-  UINT32  KernelTaggsAddress;

-  UINT32  PageSize;

-  UINT32  Reserved[2];

-  CHAR8   ProductName[16];

-  CHAR8   KernelArgs[BOOTIMG_KERNEL_ARGS_SIZE];

-  UINT32  Id[32];

-} ANDROID_BOOTIMG_HEADER;

-#pragma pack()

-

 // Find the kernel and ramdisk in an Android boot.img.

 // return EFI_INVALID_PARAMTER if the boot.img is invalid (i.e. doesn't have the

 //  right magic value),

diff --git a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c
index b891c07..11a49f5 100644
--- a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c
+++ b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.c
@@ -196,6 +196,66 @@
 }

 

 STATIC

+EFI_STATUS

+HandleKernel (

+  IN CHAR8 *PartitionName

+  )

+{

+  VOID       *BootBuffer;

+  UINTN       BootSize = 0;

+  UINT32      KernelOff;

+  UINT32      RamdiskOff;

+  UINT32      NewRamdiskOff;

+  EFI_STATUS  Status;

+  ANDROID_BOOTIMG_HEADER *Header;

+  CHAR16      OutputString[FASTBOOT_STRING_MAX_LENGTH];

+

+  Header = (ANDROID_BOOTIMG_HEADER *)mDataBuffer;

+  if ((AsciiStrnCmp (Header->BootMagic, BOOT_MAGIC, BOOT_MAGIC_LENGTH) == 0) &&

+      (Header->RamdiskSize != 0)) {

+    mTextOut->OutputString (mTextOut, L"It is boot.img\r\n");

+    return EFI_INVALID_PARAMETER;

+  }

+  mTextOut->OutputString (mTextOut, L"Booting downloaded kernel\r\n");

+  Status = mPlatform->ReadPartition (

+                        PartitionName,

+                        &BootSize,

+                        &BootBuffer);

+  if (EFI_ERROR (Status)) {

+    UnicodeSPrint (OutputString, sizeof (OutputString), L"Fastboot: Fail to read %a partition: %r\r\n", PartitionName, Status);

+    mTextOut->OutputString (mTextOut, OutputString);

+    return Status;

+  }

+
+  Header = (ANDROID_BOOTIMG_HEADER *)BootBuffer;

+  if (AsciiStrnCmp (Header->BootMagic, BOOT_MAGIC, BOOT_MAGIC_LENGTH) != 0) {

+    return EFI_INVALID_PARAMETER;

+  }

+  KernelOff = Header->PageSize;

+  RamdiskOff = KernelOff +

+               Header->PageSize *

+               ((Header->KernelSize + Header->PageSize - 1) / Header->PageSize);

+  if (mNumDataBytes < KernelOff) {

+    return EFI_INVALID_PARAMETER;

+  }

+  Header->KernelSize = mNumDataBytes - KernelOff;

+  NewRamdiskOff = KernelOff +

+               Header->PageSize *

+               ((Header->KernelSize + Header->PageSize - 1) / Header->PageSize);

+  if (NewRamdiskOff + Header->RamdiskSize > BootSize) {

+    return EFI_INVALID_PARAMETER;

+  }

+  CopyMem(BootBuffer + NewRamdiskOff, BootBuffer + RamdiskOff, Header->RamdiskSize);

+  CopyMem(BootBuffer + KernelOff, mDataBuffer + KernelOff, Header->KernelSize);

+  FreePool (mDataBuffer);

+  Status = BootAndroidBootImg (NewRamdiskOff + Header->RamdiskSize, BootBuffer);

+  if (EFI_ERROR (Status)) {

+    DEBUG ((EFI_D_ERROR, "Fastboot: Couldn't boot with new kernel: %r\n", Status));

+  }

+  return Status;

+}

+

+STATIC

 VOID

 HandleBoot (

   VOID

@@ -215,9 +275,12 @@
   // boot we lose control of the system.

   SEND_LITERAL ("OKAY");

 

-  Status = BootAndroidBootImg (mNumDataBytes, mDataBuffer);

+  Status = HandleKernel ("boot");

   if (EFI_ERROR (Status)) {

-    DEBUG ((EFI_D_ERROR, "Failed to boot downloaded image: %r\n", Status));

+    Status = BootAndroidBootImg (mNumDataBytes, mDataBuffer);

+    if (EFI_ERROR (Status)) {

+      DEBUG ((EFI_D_ERROR, "Failed to boot downloaded image: %r\n", Status));

+    }

   }

   // We shouldn't get here

 }

diff --git a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.h b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.h
index f62660f..268a0d8 100644
--- a/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.h
+++ b/EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.h
@@ -23,6 +23,26 @@
 

 #define ANDROID_FASTBOOT_VERSION "0.4"

 

+#define BOOT_MAGIC        "ANDROID!"

+#define BOOT_MAGIC_LENGTH sizeof(BOOT_MAGIC) - 1

+#pragma pack(1)

+typedef struct {

+  CHAR8   BootMagic[BOOT_MAGIC_LENGTH];

+  UINT32  KernelSize;

+  UINT32  KernelAddress;

+  UINT32  RamdiskSize;

+  UINT32  RamdiskAddress;

+  UINT32  SecondStageBootloaderSize;

+  UINT32  SecondStageBootloaderAddress;

+  UINT32  KernelTaggsAddress;

+  UINT32  PageSize;

+  UINT32  Reserved[2];

+  CHAR8   ProductName[16];

+  CHAR8   KernelArgs[BOOTIMG_KERNEL_ARGS_SIZE];

+  UINT32  Id[32];

+} ANDROID_BOOTIMG_HEADER;

+#pragma pack()

+

 EFI_STATUS

 BootAndroidBootImg (

   IN  UINTN    BufferSize,

diff --git a/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h b/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h
index d0693c1..efb8613 100644
--- a/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h
+++ b/EmbeddedPkg/Include/Protocol/AndroidFastbootPlatform.h
@@ -133,6 +133,14 @@
   IN  CHAR8   *Command

   );

 

+typedef

+EFI_STATUS

+(*FASTBOOT_PLATFORM_READ) (

+  IN CHAR8     *PartitionName,

+  IN OUT UINTN *BufferSize,

+  OUT VOID    **Buffer

+  );

+

 typedef struct _FASTBOOT_PLATFORM_PROTOCOL {

   FASTBOOT_PLATFORM_INIT          Init;

   FASTBOOT_PLATFORM_UN_INIT       UnInit;

@@ -140,6 +148,7 @@
   FASTBOOT_PLATFORM_ERASE         ErasePartition;

   FASTBOOT_PLATFORM_GETVAR        GetVar;

   FASTBOOT_PLATFORM_OEM_COMMAND   DoOemCommand;

+  FASTBOOT_PLATFORM_READ          ReadPartition;

 } FASTBOOT_PLATFORM_PROTOCOL;

 

 /* See sparse_format.h in AOSP  */