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