1 /** @file
2 
3   Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>
4 
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "AndroidFastbootApp.h"
16 
17 #define BOOT_MAGIC        "ANDROID!"
18 #define BOOT_MAGIC_LENGTH sizeof (BOOT_MAGIC) - 1
19 
20 // Check Val (unsigned) is a power of 2 (has only one bit set)
21 #define IS_POWER_OF_2(Val) (Val != 0 && ((Val & (Val - 1)) == 0))
22 
23 // No documentation for this really - sizes of fields has been determined
24 // empirically.
25 #pragma pack(1)
26 typedef struct {
27   CHAR8   BootMagic[BOOT_MAGIC_LENGTH];
28   UINT32  KernelSize;
29   UINT32  KernelAddress;
30   UINT32  RamdiskSize;
31   UINT32  RamdiskAddress;
32   UINT32  SecondStageBootloaderSize;
33   UINT32  SecondStageBootloaderAddress;
34   UINT32  KernelTaggsAddress;
35   UINT32  PageSize;
36   UINT32  Reserved[2];
37   CHAR8   ProductName[16];
38   CHAR8   KernelArgs[BOOTIMG_KERNEL_ARGS_SIZE];
39   UINT32  Id[32];
40 } ANDROID_BOOTIMG_HEADER;
41 #pragma pack()
42 
43 // Find the kernel and ramdisk in an Android boot.img.
44 // return EFI_INVALID_PARAMTER if the boot.img is invalid (i.e. doesn't have the
45 //  right magic value),
46 // return EFI_NOT_FOUND if there was no kernel in the boot.img.
47 // Note that the Ramdisk is optional - *Ramdisk won't be touched if it isn't
48 // present, but RamdiskSize will be set to 0.
49 EFI_STATUS
ParseAndroidBootImg(IN VOID * BootImg,OUT VOID ** Kernel,OUT UINTN * KernelSize,OUT VOID ** Ramdisk,OUT UINTN * RamdiskSize,OUT CHAR8 * KernelArgs)50 ParseAndroidBootImg (
51   IN  VOID    *BootImg,
52   OUT VOID   **Kernel,
53   OUT UINTN   *KernelSize,
54   OUT VOID   **Ramdisk,
55   OUT UINTN   *RamdiskSize,
56   OUT CHAR8   *KernelArgs
57   )
58 {
59   ANDROID_BOOTIMG_HEADER   *Header;
60   UINT8                    *BootImgBytePtr;
61 
62   // Cast to UINT8 so we can do pointer arithmetic
63   BootImgBytePtr = (UINT8 *) BootImg;
64 
65   Header = (ANDROID_BOOTIMG_HEADER *) BootImg;
66 
67   if (AsciiStrnCmp (Header->BootMagic, BOOT_MAGIC, BOOT_MAGIC_LENGTH) != 0) {
68     return EFI_INVALID_PARAMETER;
69   }
70 
71   if (Header->KernelSize == 0) {
72     return EFI_NOT_FOUND;
73   }
74 
75   ASSERT (IS_POWER_OF_2 (Header->PageSize));
76 
77   *KernelSize = Header->KernelSize;
78   *Kernel = BootImgBytePtr + Header->PageSize;
79   *RamdiskSize = Header->RamdiskSize;
80 
81   if (Header->RamdiskSize != 0) {
82     *Ramdisk = (VOID *) (BootImgBytePtr
83                  + Header->PageSize
84                  + ALIGN_VALUE (Header->KernelSize, Header->PageSize));
85   }
86 
87   AsciiStrnCpy (KernelArgs, Header->KernelArgs, BOOTIMG_KERNEL_ARGS_SIZE);
88 
89   return EFI_SUCCESS;
90 }
91