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