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