• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
FreePartitionList(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
ReadPartitionEntries(IN EFI_BLOCK_IO_PROTOCOL * BlockIo,OUT EFI_PARTITION_ENTRY ** PartitionEntries,OUT UINTN * PartitionNumbers)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
LoadPtable(VOID)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
HiKey960FastbootPlatformInit(VOID)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
HiKey960FastbootPlatformUnInit(VOID)273 HiKey960FastbootPlatformUnInit (
274   VOID
275   )
276 {
277   FreePartitionList ();
278 }
279 
280 EFI_STATUS
HiKey960FlashPtable(IN UINTN Size,IN VOID * Image)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
HiKey960ErasePtable(VOID)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
HiKey960FlashXloader(IN UINTN Size,IN VOID * Image)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
HiKey960FastbootPlatformFlashPartition(IN CHAR8 * PartitionName,IN UINTN Size,IN VOID * Image)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
HiKey960FastbootPlatformErasePartition(IN CHAR8 * PartitionName)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
HiKey960FastbootPlatformGetVar(IN CHAR8 * Name,OUT CHAR8 * Value)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
HiKey960FastbootPlatformOemCommand(IN CHAR8 * Command)609 HiKey960FastbootPlatformOemCommand (
610   IN  CHAR8   *Command
611   )
612 {
613   EFI_STATUS   Status;
614   CHAR16       UnicodeSN[SERIAL_NUMBER_SIZE];
615   UINTN        Size;
616 
617   Size = AsciiStrLen ("serialno");
618   if (AsciiStrCmp (Command, "Demonstrate") == 0) {
619     DEBUG ((DEBUG_ERROR, "ARM OEM Fastboot command 'Demonstrate' received.\n"));
620     return EFI_SUCCESS;
621   } else if (AsciiStrnCmp (Command, "serialno", Size) == 0) {
622     while (*(Command + Size) == ' ') {
623       Size++;
624     }
625     if (AsciiStrnCmp (Command + Size, "set", AsciiStrLen ("set")) == 0) {
626       Size += AsciiStrLen ("set");
627       while (*(Command + Size) == ' ') {
628         Size++;
629       }
630       Status = AssignUsbSN (Command + Size, UnicodeSN);
631       if (EFI_ERROR (Status)) {
632         DEBUG ((DEBUG_ERROR, "Failed to set USB Serial Number.\n"));
633         return Status;
634       }
635     } else {
636       Status = GenerateUsbSN (UnicodeSN);
637       if (EFI_ERROR (Status)) {
638         DEBUG ((DEBUG_ERROR, "Failed to generate USB Serial Number.\n"));
639         return Status;
640       }
641     }
642     Status = StoreSNToBlock (mFlashHandle, SERIAL_NUMBER_LBA, UnicodeSN);
643     return Status;
644   } else if (AsciiStrCmp (Command, "reboot-bootloader") == 0) {
645     MmioWrite32 (ADB_REBOOT_ADDRESS, ADB_REBOOT_BOOTLOADER);
646     WriteBackInvalidateDataCacheRange ((VOID *)ADB_REBOOT_ADDRESS, 4);
647     return EFI_SUCCESS;
648   } else {
649     DEBUG ((DEBUG_ERROR,
650       "HiKey960: Unrecognised Fastboot OEM command: %a\n",
651       Command
652       ));
653     return EFI_NOT_FOUND;
654   }
655 }
656 
657 EFI_STATUS
HiKey960FastbootPlatformFlashPartitionEx(IN CHAR8 * PartitionName,IN UINTN Offset,IN UINTN Size,IN VOID * Image)658 HiKey960FastbootPlatformFlashPartitionEx (
659   IN CHAR8  *PartitionName,
660   IN UINTN   Offset,
661   IN UINTN   Size,
662   IN VOID   *Image
663   )
664 {
665   EFI_STATUS               Status;
666   UINTN                    PartitionSize;
667   FASTBOOT_PARTITION_LIST *Entry;
668   CHAR16                   PartitionNameUnicode[60];
669   BOOLEAN                  PartitionFound;
670   UINTN                    BlockSize;
671   EFI_DISK_IO_PROTOCOL    *DiskIo;
672 
673   AsciiStrToUnicodeStr (PartitionName, PartitionNameUnicode);
674   PartitionFound = FALSE;
675   Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead));
676   while (!IsNull (&mPartitionListHead, &Entry->Link)) {
677     // Search the partition list for the partition named by PartitionName
678     if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) {
679       PartitionFound = TRUE;
680       break;
681     }
682 
683    Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link);
684   }
685   if (!PartitionFound) {
686     return EFI_NOT_FOUND;
687   }
688 
689   // Check image will fit on device
690   PartitionSize = (Entry->EndingLBA - Entry->StartingLBA + 1) * mFlashBlockIo->Media->BlockSize;
691   if (PartitionSize < Size) {
692     DEBUG ((DEBUG_ERROR, "Partition not big enough.\n"));
693     DEBUG ((DEBUG_ERROR, "Partition Size:\t%ld\nImage Size:\t%ld\n", PartitionSize, Size));
694 
695     return EFI_VOLUME_FULL;
696   }
697 
698   BlockSize = mFlashBlockIo->Media->BlockSize;
699 
700   Status = gBS->OpenProtocol (
701                   mFlashHandle,
702                   &gEfiDiskIoProtocolGuid,
703                   (VOID **) &DiskIo,
704                   gImageHandle,
705                   NULL,
706                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
707                   );
708   if (EFI_ERROR (Status)) {
709     return Status;
710   }
711 
712   Status = DiskIo->WriteDisk (
713                      DiskIo,
714                      mFlashBlockIo->Media->MediaId,
715                      Entry->StartingLBA * BlockSize + Offset,
716                      Size,
717                      Image
718                      );
719   if (EFI_ERROR (Status)) {
720     DEBUG ((DEBUG_ERROR, "Failed to write %d bytes into 0x%x, Status:%r\n", Size, Entry->StartingLBA * BlockSize + Offset, Status));
721     return Status;
722   }
723   return Status;
724 }
725 
726 FASTBOOT_PLATFORM_PROTOCOL mPlatformProtocol = {
727   HiKey960FastbootPlatformInit,
728   HiKey960FastbootPlatformUnInit,
729   HiKey960FastbootPlatformFlashPartition,
730   HiKey960FastbootPlatformErasePartition,
731   HiKey960FastbootPlatformGetVar,
732   HiKey960FastbootPlatformOemCommand,
733   HiKey960FastbootPlatformFlashPartitionEx
734 };
735 
736 EFI_STATUS
737 EFIAPI
HiKey960FastbootPlatformEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)738 HiKey960FastbootPlatformEntryPoint (
739   IN EFI_HANDLE                            ImageHandle,
740   IN EFI_SYSTEM_TABLE                      *SystemTable
741   )
742 {
743   return gBS->InstallProtocolInterface (
744                 &ImageHandle,
745                 &gAndroidFastbootPlatformProtocolGuid,
746                 EFI_NATIVE_INTERFACE,
747                 &mPlatformProtocol
748                 );
749 }
750