1 /** @file
2 *
3 *  Copyright (c) 2016-2017, Linaro Ltd. All rights reserved.
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 <Guid/EventGroup.h>
16 #include <Guid/HiKey960Variable.h>
17 
18 #include <Hi3660.h>
19 #include <Hkadc.h>
20 #include <libfdt.h>
21 
22 #include <Library/BaseLib.h>
23 #include <Library/BaseMemoryLib.h>
24 #include <Library/CacheMaintenanceLib.h>
25 #include <Library/DebugLib.h>
26 #include <Library/DevicePathLib.h>
27 #include <Library/MemoryAllocationLib.h>
28 #include <Library/NonDiscoverableDeviceRegistrationLib.h>
29 #include <Library/IoLib.h>
30 #include <Library/PcdLib.h>
31 #include <Library/PrintLib.h>
32 #include <Library/SerialPortLib.h>
33 #include <Library/TimerLib.h>
34 #include <Library/UefiBootServicesTableLib.h>
35 #include <Library/UefiRuntimeServicesTableLib.h>
36 
37 #include <Protocol/Abootimg.h>
38 #include <Protocol/BlockIo.h>
39 #include <Protocol/DevicePathToText.h>
40 #include <Protocol/EmbeddedGpio.h>
41 #include <Protocol/NonDiscoverableDevice.h>
42 #include <Protocol/PlatformVirtualKeyboard.h>
43 
44 #define ADC_ADCIN0                       0
45 #define ADC_ADCIN1                       1
46 #define ADC_ADCIN2                       2
47 
48 #define HKADC_DATA_GRADE0                0
49 #define HKADC_DATA_GRADE1                100
50 #define HKADC_DATA_GRADE2                300
51 #define HKADC_DATA_GRADE3                500
52 #define HKADC_DATA_GRADE4                700
53 #define HKADC_DATA_GRADE5                900
54 #define HKADC_DATA_GRADE6                1100
55 #define HKADC_DATA_GRADE7                1300
56 #define HKADC_DATA_GRADE8                1500
57 #define HKADC_DATA_GRADE9                1700
58 #define HKADC_DATA_GRADE10               1800
59 
60 #define BOARDID_VALUE0                   0
61 #define BOARDID_VALUE1                   1
62 #define BOARDID_VALUE2                   2
63 #define BOARDID_VALUE3                   3
64 #define BOARDID_VALUE4                   4
65 #define BOARDID_VALUE5                   5
66 #define BOARDID_VALUE6                   6
67 #define BOARDID_VALUE7                   7
68 #define BOARDID_VALUE8                   8
69 #define BOARDID_VALUE9                   9
70 #define BOARDID_UNKNOW                   0xF
71 
72 #define BOARDID3_BASE                    5
73 
74 #define HIKEY960_BOARDID_V1              5300
75 #define HIKEY960_BOARDID_V2              5301
76 
77 #define HIKEY960_COMPATIBLE_LEDS_V1      "gpio-leds_v1"
78 #define HIKEY960_COMPATIBLE_LEDS_V2      "gpio-leds_v2"
79 #define HIKEY960_COMPATIBLE_HUB_V1       "hisilicon,gpio_hubv1"
80 #define HIKEY960_COMPATIBLE_HUB_V2       "hisilicon,gpio_hubv2"
81 
82 #define SERIAL_NUMBER_SIZE               17
83 #define SERIAL_NUMBER_BLOCK_SIZE         EFI_PAGE_SIZE
84 #define SERIAL_NUMBER_LBA                20
85 #define RANDOM_MAX                       0x7FFFFFFFFFFFFFFF
86 #define RANDOM_MAGIC                     0x9A4DBEAF
87 
88 #define ADB_REBOOT_ADDRESS               0x32100000
89 #define ADB_REBOOT_BOOTLOADER            0x77665500
90 #define ADB_REBOOT_NONE                  0x77665501
91 
92 #define DETECT_SW_FASTBOOT               68        // GPIO8_4
93 
94 typedef struct {
95   UINT64        Magic;
96   UINT64        Data;
97   CHAR16        UnicodeSN[SERIAL_NUMBER_SIZE];
98 } RANDOM_SERIAL_NUMBER;
99 
100 enum {
101   BOOT_MODE_RECOVERY  = 0,
102   BOOT_MODE_NORMAL,
103   BOOT_MODE_MASK = 1,
104 };
105 
106 STATIC UINTN    mBoardId;
107 STATIC UINTN    mRebootUpdated;
108 STATIC UINTN    mRebootReason;
109 
110 STATIC EMBEDDED_GPIO   *mGpio;
111 
112 STATIC
113 VOID
InitAdc(VOID)114 InitAdc (
115   VOID
116   )
117 {
118   // reset hkadc
119   MmioWrite32 (CRG_PERRSTEN2, PERRSTEN2_HKADCSSI);
120   // wait a few clock cycles
121   MicroSecondDelay (2);
122   MmioWrite32 (CRG_PERRSTDIS2, PERRSTEN2_HKADCSSI);
123   MicroSecondDelay (2);
124   // enable hkadc clock
125   MmioWrite32 (CRG_PERDIS2, PEREN2_HKADCSSI);
126   MicroSecondDelay (2);
127   MmioWrite32 (CRG_PEREN2, PEREN2_HKADCSSI);
128   MicroSecondDelay (2);
129 }
130 
131 STATIC
132 EFI_STATUS
AdcGetAdc(IN UINTN Channel,OUT UINTN * Value)133 AdcGetAdc (
134   IN  UINTN         Channel,
135   OUT UINTN         *Value
136   )
137 {
138   UINT32            Data;
139   UINT16            Value1, Value0;
140 
141   if (Channel > HKADC_CHANNEL_MAX) {
142     DEBUG ((DEBUG_ERROR, "invalid channel:%d\n", Channel));
143     return EFI_OUT_OF_RESOURCES;
144   }
145   // configure the read/write operation for external HKADC
146   MmioWrite32 (HKADC_WR01_DATA, HKADC_WR01_VALUE | Channel);
147   MmioWrite32 (HKADC_WR23_DATA, HKADC_WR23_VALUE);
148   MmioWrite32 (HKADC_WR45_DATA, HKADC_WR45_VALUE);
149   // configure the number of accessing registers
150   MmioWrite32 (HKADC_WR_NUM, HKADC_WR_NUM_VALUE);
151   // configure delay of accessing registers
152   MmioWrite32 (HKADC_DELAY01, HKADC_CHANNEL0_DELAY01_VALUE);
153   MmioWrite32 (HKADC_DELAY23, HKADC_DELAY23_VALUE);
154 
155   // start HKADC
156   MmioWrite32 (HKADC_DSP_START, 1);
157   do {
158     Data = MmioRead32 (HKADC_DSP_START);
159   } while (Data & 1);
160 
161   // convert AD result
162   Value1 = (UINT16)MmioRead32 (HKADC_DSP_RD2_DATA);
163   Value0 = (UINT16)MmioRead32 (HKADC_DSP_RD3_DATA);
164 
165   Data = ((Value1 << 4) & HKADC_VALUE_HIGH) | ((Value0 >> 4) & HKADC_VALUE_LOW);
166   *Value = Data;
167   return EFI_SUCCESS;
168 }
169 
170 STATIC
171 EFI_STATUS
AdcGetValue(IN UINTN Channel,IN OUT UINTN * Value)172 AdcGetValue (
173   IN UINTN         Channel,
174   IN OUT UINTN     *Value
175   )
176 {
177   EFI_STATUS       Status;
178   UINTN            Result;
179 
180   Status = AdcGetAdc (Channel, Value);
181   if (EFI_ERROR (Status)) {
182     return Status;
183   }
184 
185   // convert ADC value to micro-volt
186   Result = ((*Value & HKADC_VALID_VALUE) * HKADC_VREF_1V8) / HKADC_ACCURACY;
187   *Value = Result;
188   return EFI_SUCCESS;
189 }
190 
191 STATIC
192 UINTN
AdcinDataRemap(IN UINTN AdcinValue)193 AdcinDataRemap (
194   IN UINTN           AdcinValue
195   )
196 {
197   UINTN              Result;
198 
199   if (AdcinValue < HKADC_DATA_GRADE0) {
200     Result = BOARDID_UNKNOW;
201   } else if (AdcinValue < HKADC_DATA_GRADE1) {
202     Result = BOARDID_VALUE0;
203   } else if (AdcinValue < HKADC_DATA_GRADE2) {
204     Result = BOARDID_VALUE1;
205   } else if (AdcinValue < HKADC_DATA_GRADE3) {
206     Result = BOARDID_VALUE2;
207   } else if (AdcinValue < HKADC_DATA_GRADE4) {
208     Result = BOARDID_VALUE3;
209   } else if (AdcinValue < HKADC_DATA_GRADE5) {
210     Result = BOARDID_VALUE4;
211   } else if (AdcinValue < HKADC_DATA_GRADE6) {
212     Result = BOARDID_VALUE5;
213   } else if (AdcinValue < HKADC_DATA_GRADE7) {
214     Result = BOARDID_VALUE6;
215   } else if (AdcinValue < HKADC_DATA_GRADE8) {
216     Result = BOARDID_VALUE7;
217   } else if (AdcinValue < HKADC_DATA_GRADE9) {
218     Result = BOARDID_VALUE8;
219   } else if (AdcinValue < HKADC_DATA_GRADE10) {
220     Result = BOARDID_VALUE9;
221   } else {
222     Result = BOARDID_UNKNOW;
223   }
224   return Result;
225 }
226 
227 STATIC
228 EFI_STATUS
InitBoardId(OUT UINTN * Id)229 InitBoardId (
230   OUT UINTN          *Id
231   )
232 {
233   UINTN              Adcin0, Adcin1, Adcin2;
234   UINTN              Adcin0Remap, Adcin1Remap, Adcin2Remap;
235 
236   InitAdc ();
237 
238   // read ADC channel0 data
239   AdcGetValue (ADC_ADCIN0, &Adcin0);
240   DEBUG ((DEBUG_ERROR, "[BDID]Adcin0:%d\n", Adcin0));
241   Adcin0Remap = AdcinDataRemap (Adcin0);
242   DEBUG ((DEBUG_ERROR, "[BDID]Adcin0Remap:%d\n", Adcin0Remap));
243   if (Adcin0Remap == BOARDID_UNKNOW) {
244     return EFI_INVALID_PARAMETER;
245   }
246   // read ADC channel1 data
247   AdcGetValue (ADC_ADCIN1, &Adcin1);
248   DEBUG ((DEBUG_ERROR, "[BDID]Adcin1:%d\n", Adcin1));
249   Adcin1Remap = AdcinDataRemap (Adcin1);
250   DEBUG ((DEBUG_ERROR, "[BDID]Adcin1Remap:%d\n", Adcin1Remap));
251   if (Adcin1Remap == BOARDID_UNKNOW) {
252     return EFI_INVALID_PARAMETER;
253   }
254   // read ADC channel2 data
255   AdcGetValue (ADC_ADCIN2, &Adcin2);
256   DEBUG ((DEBUG_ERROR, "[BDID]Adcin2:%d\n", Adcin2));
257   Adcin2Remap = AdcinDataRemap (Adcin2);
258   DEBUG ((DEBUG_ERROR, "[BDID]Adcin2Remap:%d\n", Adcin2Remap));
259   if (Adcin2Remap == BOARDID_UNKNOW) {
260     return EFI_INVALID_PARAMETER;
261   }
262   *Id = BOARDID3_BASE * 1000 + (Adcin2Remap * 100) + (Adcin1Remap * 10) + Adcin0Remap;
263   DEBUG ((DEBUG_ERROR, "[BDID]boardid: %d\n", *Id));
264   return EFI_SUCCESS;
265 }
266 
267 STATIC
268 VOID
InitSdCard(IN VOID)269 InitSdCard (
270   IN VOID
271   )
272 {
273   UINT32        Data;
274 
275   // LDO16
276   Data = MmioRead32 (PMU_REG_BASE + (0x79 << 2)) & 7;
277   Data |= 6;
278   MmioWrite32 (PMU_REG_BASE + (0x79 << 2), Data);
279   MmioOr32 (PMU_REG_BASE + (0x78 << 2), 2);
280   MicroSecondDelay (100);
281 
282   // LDO9
283   Data = MmioRead32 (PMU_REG_BASE + (0x6b << 2)) & 7;
284   Data |= 5;
285   MmioWrite32 (PMU_REG_BASE + (0x6b << 2), Data);
286   MmioOr32 (PMU_REG_BASE + (0x6a << 2), 2);
287   MicroSecondDelay (100);
288 
289   // GPIO203
290   MmioWrite32 (0xfff11000 + (24 << 2), 0); // GPIO function
291 
292   // SD pinmux
293   MmioWrite32 (0xff37e000 + 0x0, 1); // SD_CLK
294   MmioWrite32 (0xff37e000 + 0x4, 1); // SD_CMD
295   MmioWrite32 (0xff37e000 + 0x8, 1); // SD_DATA0
296   MmioWrite32 (0xff37e000 + 0xc, 1); // SD_DATA1
297   MmioWrite32 (0xff37e000 + 0x10, 1); // SD_DATA2
298   MmioWrite32 (0xff37e000 + 0x14, 1); // SD_DATA3
299   MmioWrite32 (0xff37e800 + 0x0, 15 << 4); // SD_CLK float with 32mA
300   MmioWrite32 (0xff37e800 + 0x4, (1 << 0) | (8 << 4)); // SD_CMD
301   MmioWrite32 (0xff37e800 + 0x8, (1 << 0) | (8 << 4)); // SD_DATA0
302   MmioWrite32 (0xff37e800 + 0xc, (1 << 0) | (8 << 4)); // SD_DATA1
303   MmioWrite32 (0xff37e800 + 0x10, (1 << 0) | (8 << 4)); // SD_DATA2
304   MmioWrite32 (0xff37e800 + 0x14, (1 << 0) | (8 << 4)); // SD_DATA3
305 
306   do {
307     MmioOr32 (CRG_REG_BASE + 0xb8, (1 << 6) | (1 << 6 << 16) | (0 << 4) | (3 << 4 << 16));
308     Data = MmioRead32 (CRG_REG_BASE + 0xb8);
309   } while ((Data & ((1 << 6) | (3 << 4))) != ((1 << 6) | (0 << 4)));
310 
311   // Unreset SD controller
312   MmioWrite32 (CRG_PERRSTDIS4, 1 << 18);
313   do {
314     Data = MmioRead32 (CRG_PERRSTSTAT4);
315   } while ((Data & (1 << 18)) == (1 << 18));
316   // Enable SD controller clock
317   MmioOr32 (CRG_REG_BASE + 0, 1 << 30);
318   MmioOr32 (CRG_REG_BASE + 0x40, 1 << 17);
319   do {
320     Data = MmioRead32 (CRG_REG_BASE + 0x48);
321   } while ((Data & (1 << 17)) != (1 << 17));
322 }
323 
324 VOID
InitPeripherals(IN VOID)325 InitPeripherals (
326   IN VOID
327   )
328 {
329   // Enable FPLL0
330   MmioOr32 (SCTRL_SCFPLLCTRL0, SCTRL_SCFPLLCTRL0_FPLL0_EN);
331 
332   InitSdCard ();
333 
334   // Enable wifi clock
335   MmioOr32 (PMIC_HARDWARE_CTRL0, PMIC_HARDWARE_CTRL0_WIFI_CLK);
336   MmioOr32 (PMIC_OSC32K_ONOFF_CTRL, PMIC_OSC32K_ONOFF_CTRL_EN_32K);
337 }
338 
339 /**
340   Notification function of the event defined as belonging to the
341   EFI_END_OF_DXE_EVENT_GROUP_GUID event group that was created in
342   the entry point of the driver.
343 
344   This function is called when an event belonging to the
345   EFI_END_OF_DXE_EVENT_GROUP_GUID event group is signalled. Such an
346   event is signalled once at the end of the dispatching of all
347   drivers (end of the so called DXE phase).
348 
349   @param[in]  Event    Event declared in the entry point of the driver whose
350                        notification function is being invoked.
351   @param[in]  Context  NULL
352 **/
353 STATIC
354 VOID
OnEndOfDxe(IN EFI_EVENT Event,IN VOID * Context)355 OnEndOfDxe (
356   IN EFI_EVENT  Event,
357   IN VOID       *Context
358   )
359 {
360   UINT32        BootMode;
361 
362   BootMode = MmioRead32 (SCTRL_BAK_DATA0) & BOOT_MODE_MASK;
363   if (BootMode == BOOT_MODE_RECOVERY) {
364     SerialPortWrite ((UINT8 *)"WARNING: CAN NOT BOOT KERNEL IN RECOVERY MODE!\r\n", 48);
365     SerialPortWrite ((UINT8 *)"Switch to normal boot mode, then reboot to boot kernel.\r\n", 57);
366   }
367 }
368 
369 EFI_STATUS
370 EFIAPI
AbootimgAppendKernelArgs(IN CHAR16 * Args,IN UINTN Size)371 AbootimgAppendKernelArgs (
372   IN CHAR16            *Args,
373   IN UINTN              Size
374   )
375 {
376   EFI_STATUS                  Status;
377   EFI_BLOCK_IO_PROTOCOL      *BlockIoProtocol;
378   VOID                       *DataPtr;
379   RANDOM_SERIAL_NUMBER       *RandomSN;
380   EFI_DEVICE_PATH_PROTOCOL   *FlashDevicePath;
381   EFI_HANDLE                  FlashHandle;
382 
383   if (Args == NULL) {
384     return EFI_INVALID_PARAMETER;
385   }
386   FlashDevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdAndroidFastbootNvmDevicePath));
387   Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &FlashDevicePath, &FlashHandle);
388   if (EFI_ERROR (Status)) {
389     DEBUG ((DEBUG_ERROR, "Warning: Couldn't locate Android NVM device (status: %r)\n", Status));
390     // Failing to locate partitions should not prevent to do other Android FastBoot actions
391     return EFI_SUCCESS;
392   }
393   Status = gBS->OpenProtocol (
394                   FlashHandle,
395                   &gEfiBlockIoProtocolGuid,
396                   (VOID **) &BlockIoProtocol,
397                   gImageHandle,
398                   NULL,
399                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
400                   );
401   if (EFI_ERROR (Status)) {
402     DEBUG ((DEBUG_WARN, "Warning: Couldn't open block device (status: %r)\n", Status));
403     return EFI_DEVICE_ERROR;
404   }
405 
406   DataPtr = AllocatePages (1);
407   if (DataPtr == NULL) {
408     return EFI_BUFFER_TOO_SMALL;
409   }
410   Status = BlockIoProtocol->ReadBlocks (
411                               BlockIoProtocol,
412                               BlockIoProtocol->Media->MediaId,
413                               SERIAL_NUMBER_LBA,
414                               SERIAL_NUMBER_BLOCK_SIZE,
415                               DataPtr
416                               );
417   if (EFI_ERROR (Status)) {
418     DEBUG ((DEBUG_WARN, "Warning: Failed on reading blocks\n"));
419     goto Exit;
420   }
421   RandomSN = (RANDOM_SERIAL_NUMBER *)DataPtr;
422   if (RandomSN->Magic != RANDOM_MAGIC) {
423     UnicodeSPrint(
424       RandomSN->UnicodeSN, SERIAL_NUMBER_SIZE * sizeof (CHAR16),
425       L"0123456789abcdef"
426       );
427   }
428   if (mBoardId == HIKEY960_BOARDID_V1) {
429     UnicodeSPrint (
430       Args + StrLen (Args), Size - StrLen (Args),
431       L" console=ttyAMA5 androidboot.serialno=%s",
432       RandomSN->UnicodeSN
433       );
434   } else {
435     UnicodeSPrint (
436       Args + StrLen (Args), Size - StrLen (Args),
437       L" console=ttyAMA6 androidboot.serialno=%s",
438       RandomSN->UnicodeSN
439       );
440   }
441   FreePages (DataPtr, 1);
442   return EFI_SUCCESS;
443 Exit:
444   FreePages (DataPtr, 1);
445   return Status;
446 }
447 
448 EFI_STATUS
449 EFIAPI
AbootimgUpdateDtb(IN EFI_PHYSICAL_ADDRESS OrigFdtBase,OUT EFI_PHYSICAL_ADDRESS * NewFdtBase)450 AbootimgUpdateDtb (
451   IN  EFI_PHYSICAL_ADDRESS        OrigFdtBase,
452   OUT EFI_PHYSICAL_ADDRESS       *NewFdtBase
453   )
454 {
455   //UINT8            *FdtPtr;
456   UINTN             FdtSize, NumPages;
457   INTN              err, offset;
458   EFI_STATUS        Status;
459 
460   //
461   // Sanity checks on the original FDT blob.
462   //
463   err = fdt_check_header ((VOID*)(UINTN)OrigFdtBase);
464   if (err != 0) {
465     DEBUG ((DEBUG_ERROR, "ERROR: Device Tree header not valid (err:%d)\n", err));
466     return EFI_INVALID_PARAMETER;
467   }
468 
469   //
470   // Store the FDT as Runtime Service Data to prevent the Kernel from
471   // overwritting its data.
472   //
473   FdtSize = fdt_totalsize ((VOID *)(UINTN)OrigFdtBase);
474   NumPages = EFI_SIZE_TO_PAGES (FdtSize) + 20;
475   Status = gBS->AllocatePages (
476                   AllocateAnyPages, EfiRuntimeServicesData,
477                   NumPages, NewFdtBase);
478   if (EFI_ERROR (Status)) {
479     return EFI_BUFFER_TOO_SMALL;
480   }
481 
482   CopyMem (
483     (VOID*)(UINTN)*NewFdtBase,
484     (VOID*)(UINTN)OrigFdtBase,
485     FdtSize
486     );
487 
488   if (mBoardId == HIKEY960_BOARDID_V1) {
489     offset = fdt_node_offset_by_compatible (
490                (VOID*)(UINTN)*NewFdtBase, -1, HIKEY960_COMPATIBLE_LEDS_V1
491                );
492   } else {
493     offset = fdt_node_offset_by_compatible (
494                (VOID*)(UINTN)*NewFdtBase, -1, HIKEY960_COMPATIBLE_LEDS_V2
495                );
496   }
497   // Ignore it if can't find LED compatible
498   if (offset < 0) {
499     DEBUG ((DEBUG_WARN, "WARN: Failed to find node with compatible (err:%d)\n", err));
500     goto Exit;
501   }
502   err = fdt_setprop_string ((VOID*)(UINTN)*NewFdtBase, offset, "status", "ok");
503   if (err) {
504     DEBUG ((DEBUG_ERROR, "ERROR: Failed to update status property\n"));
505     return EFI_INVALID_PARAMETER;
506   }
507   err = fdt_set_name ((VOID*)(UINTN)*NewFdtBase, offset, "gpio-leds");
508   if (err) {
509     DEBUG ((DEBUG_ERROR, "ERROR: Failed to update compatible name\n"));
510     return EFI_INVALID_PARAMETER;
511   }
512 
513   if (mBoardId == HIKEY960_BOARDID_V1) {
514     offset = fdt_node_offset_by_compatible (
515                (VOID*)(UINTN)*NewFdtBase, -1, HIKEY960_COMPATIBLE_HUB_V1
516                );
517   } else {
518     offset = fdt_node_offset_by_compatible (
519                (VOID*)(UINTN)*NewFdtBase, -1, HIKEY960_COMPATIBLE_HUB_V2
520                );
521   }
522   // Ignore it if can't find LED compatible
523   if (offset < 0) {
524     DEBUG ((DEBUG_WARN, "WARN: Failed to find node with compatible (err:%d)\n", err));
525     goto Exit;
526   }
527   err = fdt_setprop_string ((VOID*)(UINTN)*NewFdtBase, offset, "status", "ok");
528   if (err) {
529     DEBUG ((DEBUG_ERROR, "ERROR: Failed to update status property\n"));
530     return EFI_INVALID_PARAMETER;
531   }
532 
533 Exit:
534   fdt_pack ((VOID*)(UINTN)*NewFdtBase);
535   err = fdt_check_header ((VOID*)(UINTN)*NewFdtBase);
536   if (err != 0) {
537     DEBUG ((DEBUG_ERROR, "ERROR: Device Tree header not valid (err:%d)\n", err));
538     gBS->FreePages (*NewFdtBase, NumPages);
539     return EFI_INVALID_PARAMETER;
540   }
541 
542   return EFI_SUCCESS;
543 }
544 
545 ABOOTIMG_PROTOCOL mAbootimg = {
546   AbootimgAppendKernelArgs,
547   AbootimgUpdateDtb
548 };
549 
550 EFI_STATUS
551 EFIAPI
VirtualKeyboardRegister(IN VOID)552 VirtualKeyboardRegister (
553   IN VOID
554   )
555 {
556   EFI_STATUS           Status;
557 
558   Status = gBS->LocateProtocol (
559                   &gEmbeddedGpioProtocolGuid,
560                   NULL,
561                   (VOID **) &mGpio
562                   );
563   if (EFI_ERROR (Status)) {
564     return Status;
565   }
566   return EFI_SUCCESS;
567 }
568 
569 EFI_STATUS
570 EFIAPI
VirtualKeyboardReset(IN VOID)571 VirtualKeyboardReset (
572   IN VOID
573   )
574 {
575   EFI_STATUS           Status;
576 
577   if (mGpio == NULL) {
578     return EFI_INVALID_PARAMETER;
579   }
580   // Configure GPIO68 as GPIO function
581   MmioWrite32 (0xe896c108, 0);
582   Status = mGpio->Set (mGpio, DETECT_SW_FASTBOOT, GPIO_MODE_INPUT);
583   return Status;
584 }
585 
586 BOOLEAN
587 EFIAPI
VirtualKeyboardQuery(IN VIRTUAL_KBD_KEY * VirtualKey)588 VirtualKeyboardQuery (
589   IN VIRTUAL_KBD_KEY             *VirtualKey
590   )
591 {
592   EFI_STATUS           Status;
593   UINTN                Value = 0;
594 
595   if ((VirtualKey == NULL) || (mGpio == NULL)) {
596     return FALSE;
597   }
598   // If current reason doesn't match the initial one, it's updated by fastboot.
599   if (MmioRead32 (ADB_REBOOT_ADDRESS) != mRebootReason) {
600     mRebootUpdated = 1;
601   }
602   if (MmioRead32 (ADB_REBOOT_ADDRESS) == ADB_REBOOT_BOOTLOADER) {
603     goto Done;
604   } else {
605     Status = mGpio->Get (mGpio, DETECT_SW_FASTBOOT, &Value);
606     if (EFI_ERROR (Status) || (Value != 0)) {
607       return FALSE;
608     }
609   }
610 Done:
611   VirtualKey->Signature = VIRTUAL_KEYBOARD_KEY_SIGNATURE;
612   VirtualKey->Key.ScanCode = SCAN_NULL;
613   VirtualKey->Key.UnicodeChar = L'f';
614   return TRUE;
615 }
616 
617 EFI_STATUS
618 EFIAPI
VirtualKeyboardClear(IN VIRTUAL_KBD_KEY * VirtualKey)619 VirtualKeyboardClear (
620   IN VIRTUAL_KBD_KEY            *VirtualKey
621   )
622 {
623   if (VirtualKey == NULL) {
624     return EFI_INVALID_PARAMETER;
625   }
626   // Only clear the reboot flag that is set before reboot.
627   if ((MmioRead32 (ADB_REBOOT_ADDRESS) == ADB_REBOOT_BOOTLOADER) &&
628       (mRebootUpdated == 0)) {
629     MmioWrite32 (ADB_REBOOT_ADDRESS, ADB_REBOOT_NONE);
630     WriteBackInvalidateDataCacheRange ((VOID *)ADB_REBOOT_ADDRESS, 4);
631   }
632   return EFI_SUCCESS;
633 }
634 
635 PLATFORM_VIRTUAL_KBD_PROTOCOL mVirtualKeyboard = {
636   VirtualKeyboardRegister,
637   VirtualKeyboardReset,
638   VirtualKeyboardQuery,
639   VirtualKeyboardClear
640 };
641 
642 EFI_STATUS
643 EFIAPI
HiKey960EntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)644 HiKey960EntryPoint (
645   IN EFI_HANDLE         ImageHandle,
646   IN EFI_SYSTEM_TABLE   *SystemTable
647   )
648 {
649   EFI_STATUS            Status;
650   EFI_EVENT             EndOfDxeEvent;
651 
652   Status = InitBoardId (&mBoardId);
653   if (EFI_ERROR (Status)) {
654     return Status;
655   }
656 
657   InitPeripherals ();
658 
659   // Record the reboot reason if it exists
660   mRebootReason = MmioRead32 (ADB_REBOOT_ADDRESS);
661 
662   //
663   // Create an event belonging to the "gEfiEndOfDxeEventGroupGuid" group.
664   // The "OnEndOfDxe()" function is declared as the call back function.
665   // It will be called at the end of the DXE phase when an event of the
666   // same group is signalled to inform about the end of the DXE phase.
667   // Install the INSTALL_FDT_PROTOCOL protocol.
668   //
669   Status = gBS->CreateEventEx (
670                   EVT_NOTIFY_SIGNAL,
671                   TPL_CALLBACK,
672                   OnEndOfDxe,
673                   NULL,
674                   &gEfiEndOfDxeEventGroupGuid,
675                   &EndOfDxeEvent
676                   );
677   if (EFI_ERROR (Status)) {
678     return Status;
679   }
680 
681   // RegisterNonDicoverableMmioDevice
682   Status = RegisterNonDiscoverableMmioDevice (
683              NonDiscoverableDeviceTypeUfs,
684              NonDiscoverableDeviceDmaTypeNonCoherent,
685              NULL,
686              NULL,
687              1,
688              FixedPcdGet32 (PcdDwUfsHcDxeBaseAddress),
689              SIZE_4KB
690              );
691   if (EFI_ERROR (Status)) {
692     return Status;
693   }
694   Status = RegisterNonDiscoverableMmioDevice (
695              NonDiscoverableDeviceTypeSdhci,
696              NonDiscoverableDeviceDmaTypeNonCoherent,
697              NULL,
698              NULL,
699              1,
700              0xFF37F000, // SD
701              SIZE_4KB
702              );
703   if (EFI_ERROR (Status)) {
704     return Status;
705   }
706 
707   Status = gBS->InstallProtocolInterface (
708                   &ImageHandle,
709                   &gAbootimgProtocolGuid,
710                   EFI_NATIVE_INTERFACE,
711                   &mAbootimg
712                   );
713   if (EFI_ERROR (Status)) {
714     return Status;
715   }
716 
717   Status = gBS->InstallProtocolInterface (
718                   &ImageHandle,
719                   &gPlatformVirtualKeyboardProtocolGuid,
720                   EFI_NATIVE_INTERFACE,
721                   &mVirtualKeyboard
722                   );
723   return Status;
724 }
725