Home | History | Annotate | Download | only in HiKey960FastbootDxe
      1 /** @file
      2 
      3   Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
      4   Copyright (c) 2015-2017, Linaro. All rights reserved.
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 /*
     17   Implementation of the Android Fastboot Platform protocol, to be used by the
     18   Fastboot UEFI application, for Hisilicon HiKey platform.
     19 */
     20 
     21 #include <Protocol/AndroidFastbootPlatform.h>
     22 #include <Protocol/BlockIo.h>
     23 #include <Protocol/DiskIo.h>
     24 #include <Protocol/EraseBlock.h>
     25 #include <Protocol/SimpleTextOut.h>
     26 
     27 #include <Protocol/DevicePathToText.h>
     28 
     29 #include <Library/BaseLib.h>
     30 #include <Library/BaseMemoryLib.h>
     31 #include <Library/CacheMaintenanceLib.h>
     32 #include <Library/DebugLib.h>
     33 #include <Library/DevicePathLib.h>
     34 #include <Library/IoLib.h>
     35 #include <Library/MemoryAllocationLib.h>
     36 #include <Library/UefiBootServicesTableLib.h>
     37 #include <Library/UefiRuntimeServicesTableLib.h>
     38 #include <Library/UsbSerialNumberLib.h>
     39 #include <Library/PrintLib.h>
     40 #include <Library/TimerLib.h>
     41 
     42 #define PARTITION_NAME_MAX_LENGTH        (72/2)
     43 
     44 #define SERIAL_NUMBER_LBA                20
     45 #define RANDOM_MAX                       0x7FFFFFFFFFFFFFFF
     46 #define RANDOM_MAGIC                     0x9A4DBEAF
     47 
     48 #define ADB_REBOOT_ADDRESS               0x32100000
     49 #define ADB_REBOOT_BOOTLOADER            0x77665500
     50 
     51 #define UFS_BLOCK_SIZE                   4096
     52 
     53 typedef struct _FASTBOOT_PARTITION_LIST {
     54   LIST_ENTRY  Link;
     55   CHAR16      PartitionName[PARTITION_NAME_MAX_LENGTH];
     56   EFI_LBA     StartingLBA;
     57   EFI_LBA     EndingLBA;
     58 } FASTBOOT_PARTITION_LIST;
     59 
     60 STATIC LIST_ENTRY                       mPartitionListHead;
     61 STATIC EFI_HANDLE                       mFlashHandle;
     62 STATIC EFI_BLOCK_IO_PROTOCOL           *mFlashBlockIo;
     63 STATIC EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *mTextOut;
     64 
     65 /*
     66   Helper to free the partition list
     67 */
     68 STATIC
     69 VOID
     70 FreePartitionList (
     71   VOID
     72   )
     73 {
     74   FASTBOOT_PARTITION_LIST *Entry;
     75   FASTBOOT_PARTITION_LIST *NextEntry;
     76 
     77   Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&mPartitionListHead);
     78   while (!IsNull (&mPartitionListHead, &Entry->Link)) {
     79     NextEntry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &Entry->Link);
     80 
     81     RemoveEntryList (&Entry->Link);
     82     FreePool (Entry);
     83 
     84     Entry = NextEntry;
     85   }
     86 }
     87 
     88 /*
     89   Read the PartitionName fields from the GPT partition entries, putting them
     90   into an allocated array that should later be freed.
     91 */
     92 STATIC
     93 EFI_STATUS
     94 ReadPartitionEntries (
     95   IN  EFI_BLOCK_IO_PROTOCOL *BlockIo,
     96   OUT EFI_PARTITION_ENTRY  **PartitionEntries,
     97   OUT UINTN                 *PartitionNumbers
     98   )
     99 {
    100   UINT32                      MediaId;
    101   EFI_PARTITION_TABLE_HEADER *GptHeader;
    102   EFI_PARTITION_ENTRY        *Entry;
    103   EFI_STATUS                  Status;
    104   VOID                       *Buffer;
    105   UINTN                       PageCount;
    106   UINTN                       BlockSize;
    107   UINTN                       Count, EndLBA;
    108 
    109   if ((PartitionEntries == NULL) || (PartitionNumbers == NULL)) {
    110     return EFI_INVALID_PARAMETER;
    111   }
    112   MediaId = BlockIo->Media->MediaId;
    113   BlockSize = BlockIo->Media->BlockSize;
    114 
    115   //
    116   // Read size of Partition entry and number of entries from GPT header
    117   //
    118 
    119   PageCount = EFI_SIZE_TO_PAGES (6 * BlockSize);
    120   Buffer = AllocatePages (PageCount);
    121   if (Buffer == NULL) {
    122     return EFI_OUT_OF_RESOURCES;
    123   }
    124 
    125   Status = BlockIo->ReadBlocks (BlockIo, MediaId, 0, PageCount * EFI_PAGE_SIZE, Buffer);
    126   if (EFI_ERROR (Status)) {
    127     return Status;
    128   }
    129   GptHeader = (EFI_PARTITION_TABLE_HEADER *)(Buffer + BlockSize);
    130 
    131   // Check there is a GPT on the media
    132   if (GptHeader->Header.Signature != EFI_PTAB_HEADER_ID ||
    133       GptHeader->MyLBA != 1) {
    134     DEBUG ((DEBUG_ERROR,
    135       "Fastboot platform: No GPT on flash. "
    136       "Fastboot on Versatile Express does not support MBR.\n"
    137       ));
    138     return EFI_DEVICE_ERROR;
    139   }
    140 
    141   Entry = (EFI_PARTITION_ENTRY *)(Buffer + (2 * BlockSize));
    142   EndLBA = GptHeader->FirstUsableLBA - 1;
    143   Count = 0;
    144   while (1) {
    145     if ((Entry->StartingLBA > EndLBA) && (Entry->EndingLBA <= GptHeader->LastUsableLBA)) {
    146       Count++;
    147       EndLBA = Entry->EndingLBA;
    148       Entry++;
    149     } else {
    150       break;
    151     }
    152   }
    153   if (Count == 0) {
    154     return EFI_INVALID_PARAMETER;
    155   }
    156   if (Count > GptHeader->NumberOfPartitionEntries) {
    157     Count = GptHeader->NumberOfPartitionEntries;
    158   }
    159 
    160   *PartitionEntries = (EFI_PARTITION_ENTRY *)((UINTN)Buffer + (2 * BlockSize));
    161   *PartitionNumbers = Count;
    162   return EFI_SUCCESS;
    163 }
    164 
    165 EFI_STATUS
    166 LoadPtable (
    167   VOID
    168   )
    169 {
    170   EFI_STATUS                          Status;
    171   EFI_DEVICE_PATH_PROTOCOL           *FlashDevicePath;
    172   EFI_DEVICE_PATH_PROTOCOL           *FlashDevicePathDup;
    173   UINTN                               PartitionNumbers = 0;
    174   UINTN                               LoopIndex;
    175   EFI_PARTITION_ENTRY                *PartitionEntries = NULL;
    176   FASTBOOT_PARTITION_LIST            *Entry;
    177 
    178   InitializeListHead (&mPartitionListHead);
    179 
    180   Status = gBS->LocateProtocol (&gEfiSimpleTextOutProtocolGuid, NULL, (VOID **) &mTextOut);
    181   if (EFI_ERROR (Status)) {
    182     DEBUG ((DEBUG_ERROR,
    183       "Fastboot platform: Couldn't open Text Output Protocol: %r\n", Status
    184       ));
    185     return Status;
    186   }
    187 
    188   //
    189   // Get EFI_HANDLES for all the partitions on the block devices pointed to by
    190   // PcdFastbootFlashDevicePath, also saving their GPT partition labels.
    191   // There's no way to find all of a device's children, so we get every handle
    192   // in the system supporting EFI_BLOCK_IO_PROTOCOL and then filter out ones
    193   // that don't represent partitions on the flash device.
    194   //
    195   FlashDevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdAndroidFastbootNvmDevicePath));
    196 
    197   // Create another device path pointer because LocateDevicePath will modify it.
    198   FlashDevicePathDup = FlashDevicePath;
    199   Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &FlashDevicePathDup, &mFlashHandle);
    200   if (EFI_ERROR (Status)) {
    201     DEBUG ((DEBUG_ERROR, "Warning: Couldn't locate Android NVM device (status: %r)\n", Status));
    202     // Failing to locate partitions should not prevent to do other Android FastBoot actions
    203     return EFI_SUCCESS;
    204   }
    205 
    206 
    207   Status = gBS->OpenProtocol (
    208                   mFlashHandle,
    209                   &gEfiBlockIoProtocolGuid,
    210                   (VOID **) &mFlashBlockIo,
    211                   gImageHandle,
    212                   NULL,
    213                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    214                   );
    215   if (EFI_ERROR (Status)) {
    216     DEBUG ((DEBUG_ERROR, "Fastboot platform: Couldn't open Android NVM device (status: %r)\n", Status));
    217     return EFI_DEVICE_ERROR;
    218   }
    219 
    220   // Read the GPT partition entry array into memory so we can get the partition names
    221   Status = ReadPartitionEntries (mFlashBlockIo, &PartitionEntries, &PartitionNumbers);
    222   if (EFI_ERROR (Status)) {
    223     DEBUG ((DEBUG_ERROR, "Warning: Failed to read partitions from Android NVM device (status: %r)\n", Status));
    224     // Failing to locate partitions should not prevent to do other Android FastBoot actions
    225     return EFI_SUCCESS;
    226   }
    227   for (LoopIndex = 0; LoopIndex < PartitionNumbers; LoopIndex++) {
    228     // Create entry
    229     Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST));
    230     if (Entry == NULL) {
    231       Status = EFI_OUT_OF_RESOURCES;
    232       FreePartitionList ();
    233       goto Exit;
    234     }
    235     StrnCpy (
    236       Entry->PartitionName,
    237       PartitionEntries[LoopIndex].PartitionName,
    238       PARTITION_NAME_MAX_LENGTH
    239       );
    240     Entry->StartingLBA = PartitionEntries[LoopIndex].StartingLBA;
    241     Entry->EndingLBA = PartitionEntries[LoopIndex].EndingLBA;
    242     InsertTailList (&mPartitionListHead, &Entry->Link);
    243   }
    244 Exit:
    245   FreePages (
    246     (VOID *)((UINTN)PartitionEntries - (2 * mFlashBlockIo->Media->BlockSize)),
    247     EFI_SIZE_TO_PAGES (6 * mFlashBlockIo->Media->BlockSize)
    248     );
    249   return Status;
    250 }
    251 
    252 /*
    253   Initialise: Open the Android NVM device and find the partitions on it. Save them in
    254   a list along with the "PartitionName" fields for their GPT entries.
    255   We will use these partition names as the key in
    256   HiKey960FastbootPlatformFlashPartition.
    257 */
    258 EFI_STATUS
    259 HiKey960FastbootPlatformInit (
    260   VOID
    261   )
    262 {
    263   EFI_STATUS               Status;
    264 
    265   Status = LoadPtable ();
    266   if (EFI_ERROR (Status)) {
    267     return Status;
    268   }
    269   return Status;
    270 }
    271 
    272 VOID
    273 HiKey960FastbootPlatformUnInit (
    274   VOID
    275   )
    276 {
    277   FreePartitionList ();
    278 }
    279 
    280 EFI_STATUS
    281 HiKey960FlashPtable (
    282   IN UINTN   Size,
    283   IN VOID   *Image
    284   )
    285 {
    286   EFI_STATUS               Status;
    287   Status = mFlashBlockIo->WriteBlocks (
    288                             mFlashBlockIo,
    289                             mFlashBlockIo->Media->MediaId,
    290                             0,
    291                             Size,
    292                             Image
    293                             );
    294   if (EFI_ERROR (Status)) {
    295     DEBUG ((DEBUG_ERROR, "Failed to write (status:%r)\n", Status));
    296     return Status;
    297   }
    298   FreePartitionList ();
    299   Status = LoadPtable ();
    300   return Status;
    301 }
    302 
    303 EFI_STATUS
    304 HiKey960ErasePtable (
    305   VOID
    306   )
    307 {
    308   EFI_STATUS                  Status;
    309 #if 0
    310   EFI_ERASE_BLOCK_PROTOCOL   *EraseBlockProtocol;
    311 #endif
    312 
    313 #if 0
    314   Status = gBS->OpenProtocol (
    315                   mFlashHandle,
    316                   &gEfiEraseBlockProtocolGuid,
    317                   (VOID **) &EraseBlockProtocol,
    318                   gImageHandle,
    319                   NULL,
    320                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    321                   );
    322   if (EFI_ERROR (Status)) {
    323     DEBUG ((DEBUG_ERROR, "Fastboot platform: could not open Erase Block IO: %r\n", Status));
    324     return EFI_DEVICE_ERROR;
    325   }
    326   Status = EraseBlockProtocol->EraseBlocks (
    327                                  EraseBlockProtocol,
    328                                  mFlashBlockIo->Media->MediaId,
    329                                  0,
    330                                  NULL,
    331                                  6 * mFlashBlockIo->Media->BlockSize
    332                                  );
    333 #else
    334   {
    335     VOID         *DataPtr;
    336     UINTN         Lba;
    337 
    338     DataPtr = AllocatePages (1);
    339     ZeroMem (DataPtr, EFI_PAGE_SIZE);
    340     for (Lba = 0; Lba < 6; Lba++) {
    341       Status = mFlashBlockIo->WriteBlocks (
    342                           mFlashBlockIo,
    343                           mFlashBlockIo->Media->MediaId,
    344                           Lba,
    345                           EFI_PAGE_SIZE,
    346                           DataPtr
    347                           );
    348       if (EFI_ERROR (Status)) {
    349         goto Exit;
    350       }
    351     }
    352 Exit:
    353     FreePages (DataPtr, 1);
    354   }
    355 #endif
    356   FreePartitionList ();
    357   return Status;
    358 }
    359 
    360 EFI_STATUS
    361 HiKey960FlashXloader (
    362   IN UINTN   Size,
    363   IN VOID   *Image
    364   )
    365 {
    366   EFI_STATUS                        Status;
    367   EFI_DEVICE_PATH_PROTOCOL         *DevicePath;
    368   EFI_HANDLE                        Handle;
    369   EFI_BLOCK_IO_PROTOCOL            *BlockIo;
    370   EFI_DISK_IO_PROTOCOL             *DiskIo;
    371 
    372   DevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdXloaderDevicePath));
    373 
    374   Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePath, &Handle);
    375   if (EFI_ERROR (Status)) {
    376     DEBUG ((DEBUG_ERROR, "Warning: Couldn't locate xloader device (status: %r)\n", Status));
    377     return Status;
    378   }
    379 
    380   Status = gBS->OpenProtocol (
    381                   Handle,
    382                   &gEfiBlockIoProtocolGuid,
    383                   (VOID **) &BlockIo,
    384                   gImageHandle,
    385                   NULL,
    386                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    387                   );
    388   if (EFI_ERROR (Status)) {
    389     DEBUG ((DEBUG_ERROR, "Fastboot platform: Couldn't open xloader device (status: %r)\n", Status));
    390     return EFI_DEVICE_ERROR;
    391   }
    392   Status = gBS->OpenProtocol (
    393                   Handle,
    394                   &gEfiDiskIoProtocolGuid,
    395                   (VOID **) &DiskIo,
    396                   gImageHandle,
    397                   NULL,
    398                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    399                   );
    400   if (EFI_ERROR (Status)) {
    401     return Status;
    402   }
    403 
    404   Status = DiskIo->WriteDisk (
    405                      DiskIo,
    406                      BlockIo->Media->MediaId,
    407                      0,
    408                      Size,
    409                      Image
    410                      );
    411   if (EFI_ERROR (Status)) {
    412     DEBUG ((DEBUG_ERROR, "Failed to write (status:%r)\n", Status));
    413     return Status;
    414   }
    415   return Status;
    416 }
    417 
    418 EFI_STATUS
    419 HiKey960FastbootPlatformFlashPartition (
    420   IN CHAR8  *PartitionName,
    421   IN UINTN   Size,
    422   IN VOID   *Image
    423   )
    424 {
    425   EFI_STATUS               Status;
    426   UINTN                    PartitionSize;
    427   FASTBOOT_PARTITION_LIST *Entry;
    428   CHAR16                   PartitionNameUnicode[60];
    429   BOOLEAN                  PartitionFound;
    430   EFI_DISK_IO_PROTOCOL    *DiskIo;
    431   UINTN                    BlockSize;
    432 
    433   // Support the pseudo partition name, such as "ptable".
    434   if (AsciiStrCmp (PartitionName, "ptable") == 0) {
    435     return HiKey960FlashPtable (Size, Image);
    436   } else if (AsciiStrCmp (PartitionName, "xloader") == 0) {
    437     return HiKey960FlashXloader (Size, Image);
    438   }
    439 
    440   AsciiStrToUnicodeStr (PartitionName, PartitionNameUnicode);
    441   PartitionFound = FALSE;
    442   Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead));
    443   while (!IsNull (&mPartitionListHead, &Entry->Link)) {
    444     // Search the partition list for the partition named by PartitionName
    445     if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) {
    446       PartitionFound = TRUE;
    447       break;
    448     }
    449 
    450    Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link);
    451   }
    452   if (!PartitionFound) {
    453     return EFI_NOT_FOUND;
    454   }
    455 
    456   // Check image will fit on device
    457   BlockSize = mFlashBlockIo->Media->BlockSize;
    458   PartitionSize = (Entry->EndingLBA - Entry->StartingLBA + 1) * BlockSize;
    459   if (PartitionSize < Size) {
    460     DEBUG ((DEBUG_ERROR, "Partition not big enough.\n"));
    461     DEBUG ((DEBUG_ERROR, "Partition Size:\t%ld\nImage Size:\t%ld\n", PartitionSize, Size));
    462 
    463     return EFI_VOLUME_FULL;
    464   }
    465 
    466   Status = gBS->OpenProtocol (
    467                   mFlashHandle,
    468                   &gEfiDiskIoProtocolGuid,
    469                   (VOID **) &DiskIo,
    470                   gImageHandle,
    471                   NULL,
    472                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    473                   );
    474   ASSERT_EFI_ERROR (Status);
    475 
    476   Status = DiskIo->WriteDisk (
    477                      DiskIo,
    478                      mFlashBlockIo->Media->MediaId,
    479                      Entry->StartingLBA * BlockSize,
    480                      Size,
    481                      Image
    482                      );
    483   if (EFI_ERROR (Status)) {
    484     DEBUG ((DEBUG_ERROR, "Failed to write %d bytes into 0x%x, Status:%r\n", Size, Entry->StartingLBA * BlockSize, Status));
    485     return Status;
    486   }
    487 
    488   mFlashBlockIo->FlushBlocks(mFlashBlockIo);
    489   MicroSecondDelay (50000);
    490 
    491   return Status;
    492 }
    493 
    494 EFI_STATUS
    495 HiKey960FastbootPlatformErasePartition (
    496   IN CHAR8 *PartitionName
    497   )
    498 {
    499   EFI_STATUS                  Status;
    500   EFI_ERASE_BLOCK_PROTOCOL   *EraseBlockProtocol;
    501   UINTN                       Size;
    502   BOOLEAN                     PartitionFound;
    503   CHAR16                      PartitionNameUnicode[60];
    504   FASTBOOT_PARTITION_LIST    *Entry;
    505 
    506   AsciiStrToUnicodeStr (PartitionName, PartitionNameUnicode);
    507 
    508   // Support the pseudo partition name, such as "ptable".
    509   if (AsciiStrCmp (PartitionName, "ptable") == 0) {
    510     return HiKey960ErasePtable ();
    511   }
    512 
    513   PartitionFound = FALSE;
    514   Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&mPartitionListHead);
    515   while (!IsNull (&mPartitionListHead, &Entry->Link)) {
    516     // Search the partition list for the partition named by PartitionName
    517     if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) {
    518       PartitionFound = TRUE;
    519       break;
    520     }
    521     Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &Entry->Link);
    522   }
    523   if (!PartitionFound) {
    524     return EFI_NOT_FOUND;
    525   }
    526 
    527   Status = gBS->OpenProtocol (
    528                   mFlashHandle,
    529                   &gEfiEraseBlockProtocolGuid,
    530                   (VOID **) &EraseBlockProtocol,
    531                   gImageHandle,
    532                   NULL,
    533                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    534                   );
    535   if (EFI_ERROR (Status)) {
    536     return Status;
    537   }
    538   Size = (Entry->EndingLBA - Entry->StartingLBA + 1) * mFlashBlockIo->Media->BlockSize;
    539   Status = EraseBlockProtocol->EraseBlocks (
    540                                  EraseBlockProtocol,
    541                                  mFlashBlockIo->Media->MediaId,
    542                                  Entry->StartingLBA,
    543                                  NULL,
    544                                  Size
    545                                  );
    546   return Status;
    547 }
    548 
    549 EFI_STATUS
    550 HiKey960FastbootPlatformGetVar (
    551   IN  CHAR8   *Name,
    552   OUT CHAR8   *Value
    553   )
    554 {
    555   EFI_STATUS               Status = EFI_SUCCESS;
    556   UINT64                   PartitionSize;
    557   FASTBOOT_PARTITION_LIST *Entry;
    558   CHAR16                   PartitionNameUnicode[60];
    559   BOOLEAN                  PartitionFound;
    560   CHAR16                   UnicodeSN[SERIAL_NUMBER_SIZE];
    561 
    562   if (!AsciiStrCmp (Name, "max-download-size")) {
    563     AsciiStrCpy (Value, FixedPcdGetPtr (PcdArmFastbootFlashLimit));
    564   } else if (!AsciiStrCmp (Name, "product")) {
    565     AsciiStrCpy (Value, FixedPcdGetPtr (PcdFirmwareVendor));
    566   } else if (!AsciiStrCmp (Name, "serialno")) {
    567     Status = LoadSNFromBlock (mFlashHandle, SERIAL_NUMBER_LBA, UnicodeSN);
    568     UnicodeStrToAsciiStr (UnicodeSN, Value);
    569   } else if ( !AsciiStrnCmp (Name, "partition-size", 14)) {
    570     AsciiStrToUnicodeStr ((Name + 15), PartitionNameUnicode);
    571     PartitionFound = FALSE;
    572     Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead));
    573     while (!IsNull (&mPartitionListHead, &Entry->Link)) {
    574       // Search the partition list for the partition named by PartitionName
    575       if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) {
    576         PartitionFound = TRUE;
    577         break;
    578       }
    579 
    580      Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link);
    581     }
    582     if (!PartitionFound) {
    583       *Value = '\0';
    584       return EFI_NOT_FOUND;
    585     }
    586 
    587     PartitionSize = (Entry->EndingLBA - Entry->StartingLBA + 1) * mFlashBlockIo->Media->BlockSize;
    588     DEBUG ((DEBUG_ERROR, "Fastboot platform: check for partition-size:%a 0X%llx\n", Name, PartitionSize ));
    589     AsciiSPrint (Value, 12, "0x%llx", PartitionSize);
    590   } else if ( !AsciiStrnCmp (Name, "partition-type", 14)) {
    591       DEBUG ((DEBUG_ERROR, "Fastboot platform: check for partition-type:%a\n", (Name + 15) ));
    592     if ( !AsciiStrnCmp  ( (Name + 15) , "system", 6) || !AsciiStrnCmp  ( (Name + 15) , "userdata", 8)
    593             || !AsciiStrnCmp  ( (Name + 15) , "cache", 5)) {
    594       AsciiStrCpy (Value, "ext4");
    595     } else {
    596       AsciiStrCpy (Value, "raw");
    597     }
    598   } else if ( !AsciiStrCmp (Name, "erase-block-size")) {
    599     AsciiSPrint (Value, 12, "0x%llx", UFS_BLOCK_SIZE);
    600   } else if ( !AsciiStrCmp (Name, "logical-block-size")) {
    601     AsciiSPrint (Value, 12, "0x%llx", UFS_BLOCK_SIZE);
    602   } else {
    603     *Value = '\0';
    604   }
    605   return Status;
    606 }
    607 
    608 EFI_STATUS
    609 HiKey960FastbootPlatformOemCommand (
    610   IN  CHAR8   *Command
    611   )
    612 {
    613   EFI_STATUS   Status;
    614   CHAR16       UnicodeSN[SERIAL_NUMBER_SIZE];
    615 
    616   if (AsciiStrCmp (Command, "Demonstrate") == 0) {
    617     DEBUG ((DEBUG_ERROR, "ARM OEM Fastboot command 'Demonstrate' received.\n"));
    618     return EFI_SUCCESS;
    619   } else if (AsciiStrCmp (Command, "serialno") == 0) {
    620     Status = GenerateUsbSN (UnicodeSN);
    621     if (EFI_ERROR (Status)) {
    622       DEBUG ((DEBUG_ERROR, "Failed to generate USB Serial Number.\n"));
    623       return Status;
    624     }
    625     Status = StoreSNToBlock (mFlashHandle, SERIAL_NUMBER_LBA, UnicodeSN);
    626     return Status;
    627   } else if (AsciiStrCmp (Command, "reboot-bootloader") == 0) {
    628     MmioWrite32 (ADB_REBOOT_ADDRESS, ADB_REBOOT_BOOTLOADER);
    629     WriteBackInvalidateDataCacheRange ((VOID *)ADB_REBOOT_ADDRESS, 4);
    630     return EFI_SUCCESS;
    631   } else {
    632     DEBUG ((DEBUG_ERROR,
    633       "HiKey960: Unrecognised Fastboot OEM command: %a\n",
    634       Command
    635       ));
    636     return EFI_NOT_FOUND;
    637   }
    638 }
    639 
    640 EFI_STATUS
    641 HiKey960FastbootPlatformFlashPartitionEx (
    642   IN CHAR8  *PartitionName,
    643   IN UINTN   Offset,
    644   IN UINTN   Size,
    645   IN VOID   *Image
    646   )
    647 {
    648   EFI_STATUS               Status;
    649   UINTN                    PartitionSize;
    650   FASTBOOT_PARTITION_LIST *Entry;
    651   CHAR16                   PartitionNameUnicode[60];
    652   BOOLEAN                  PartitionFound;
    653   UINTN                    BlockSize;
    654   EFI_DISK_IO_PROTOCOL    *DiskIo;
    655 
    656   AsciiStrToUnicodeStr (PartitionName, PartitionNameUnicode);
    657   PartitionFound = FALSE;
    658   Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead));
    659   while (!IsNull (&mPartitionListHead, &Entry->Link)) {
    660     // Search the partition list for the partition named by PartitionName
    661     if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) {
    662       PartitionFound = TRUE;
    663       break;
    664     }
    665 
    666    Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link);
    667   }
    668   if (!PartitionFound) {
    669     return EFI_NOT_FOUND;
    670   }
    671 
    672   // Check image will fit on device
    673   PartitionSize = (Entry->EndingLBA - Entry->StartingLBA + 1) * mFlashBlockIo->Media->BlockSize;
    674   if (PartitionSize < Size) {
    675     DEBUG ((DEBUG_ERROR, "Partition not big enough.\n"));
    676     DEBUG ((DEBUG_ERROR, "Partition Size:\t%ld\nImage Size:\t%ld\n", PartitionSize, Size));
    677 
    678     return EFI_VOLUME_FULL;
    679   }
    680 
    681   BlockSize = mFlashBlockIo->Media->BlockSize;
    682 
    683   Status = gBS->OpenProtocol (
    684                   mFlashHandle,
    685                   &gEfiDiskIoProtocolGuid,
    686                   (VOID **) &DiskIo,
    687                   gImageHandle,
    688                   NULL,
    689                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    690                   );
    691   if (EFI_ERROR (Status)) {
    692     return Status;
    693   }
    694 
    695   Status = DiskIo->WriteDisk (
    696                      DiskIo,
    697                      mFlashBlockIo->Media->MediaId,
    698                      Entry->StartingLBA * BlockSize + Offset,
    699                      Size,
    700                      Image
    701                      );
    702   if (EFI_ERROR (Status)) {
    703     DEBUG ((DEBUG_ERROR, "Failed to write %d bytes into 0x%x, Status:%r\n", Size, Entry->StartingLBA * BlockSize + Offset, Status));
    704     return Status;
    705   }
    706   return Status;
    707 }
    708 
    709 FASTBOOT_PLATFORM_PROTOCOL mPlatformProtocol = {
    710   HiKey960FastbootPlatformInit,
    711   HiKey960FastbootPlatformUnInit,
    712   HiKey960FastbootPlatformFlashPartition,
    713   HiKey960FastbootPlatformErasePartition,
    714   HiKey960FastbootPlatformGetVar,
    715   HiKey960FastbootPlatformOemCommand,
    716   HiKey960FastbootPlatformFlashPartitionEx
    717 };
    718 
    719 EFI_STATUS
    720 EFIAPI
    721 HiKey960FastbootPlatformEntryPoint (
    722   IN EFI_HANDLE                            ImageHandle,
    723   IN EFI_SYSTEM_TABLE                      *SystemTable
    724   )
    725 {
    726   return gBS->InstallProtocolInterface (
    727                 &ImageHandle,
    728                 &gAndroidFastbootPlatformProtocolGuid,
    729                 EFI_NATIVE_INTERFACE,
    730                 &mPlatformProtocol
    731                 );
    732 }
    733