1 /** @file
2 *
3 *  Copyright (c) 2015-2016, Linaro Ltd. All rights reserved.
4 *  Copyright (c) 2015-2016, Hisilicon Ltd. 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 #include <Library/BaseMemoryLib.h>
17 #include <Library/CacheMaintenanceLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/DevicePathLib.h>
20 #include <Library/IoLib.h>
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/NonDiscoverableDeviceRegistrationLib.h>
23 #include <Library/PrintLib.h>
24 #include <Library/UefiBootServicesTableLib.h>
25 #include <Library/UefiLib.h>
26 #include <Library/UefiRuntimeServicesTableLib.h>
27 
28 #include <Protocol/Abootimg.h>
29 #include <Protocol/BlockIo.h>
30 #include <Protocol/EmbeddedGpio.h>
31 #include <Protocol/PlatformVirtualKeyboard.h>
32 
33 #include <Hi6220.h>
34 #include <libfdt.h>
35 
36 #include "Hi6220RegsPeri.h"
37 
38 #define SERIAL_NUMBER_SIZE               17
39 #define SERIAL_NUMBER_BLOCK_SIZE         EFI_PAGE_SIZE
40 #define SERIAL_NUMBER_LBA                1024
41 #define RANDOM_MAX                       0x7FFFFFFFFFFFFFFF
42 #define RANDOM_MAGIC                     0x9A4DBEAF
43 
44 #define DETECT_J15_FASTBOOT              24   // GPIO3_0
45 
46 #define ADB_REBOOT_ADDRESS               0x05F01000
47 #define ADB_REBOOT_BOOTLOADER            0x77665500
48 #define ADB_REBOOT_NONE                  0x77665501
49 
50 
51 typedef struct {
52   UINT64        Magic;
53   UINT64        Data;
54   CHAR16        UnicodeSN[SERIAL_NUMBER_SIZE];
55 } RANDOM_SERIAL_NUMBER;
56 
57 STATIC EMBEDDED_GPIO        *mGpio;
58 
59 STATIC
60 VOID
UartInit(IN VOID)61 UartInit (
62   IN VOID
63   )
64 {
65   UINT32     Val;
66 
67   /* make UART1 out of reset */
68   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS3, PERIPH_RST3_UART1);
69   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CLKEN3, PERIPH_RST3_UART1);
70   /* make UART2 out of reset */
71   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS3, PERIPH_RST3_UART2);
72   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CLKEN3, PERIPH_RST3_UART2);
73   /* make UART3 out of reset */
74   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS3, PERIPH_RST3_UART3);
75   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CLKEN3, PERIPH_RST3_UART3);
76   /* make UART4 out of reset */
77   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS3, PERIPH_RST3_UART4);
78   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CLKEN3, PERIPH_RST3_UART4);
79 
80   /* make DW_MMC2 out of reset */
81   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS0, PERIPH_RST0_MMC2);
82 
83   /* enable clock for BT/WIFI */
84   Val = MmioRead32 (PMUSSI_REG(0x1c)) | 0x40;
85   MmioWrite32 (PMUSSI_REG(0x1c), Val);
86 }
87 
88 STATIC
89 VOID
MtcmosInit(IN VOID)90 MtcmosInit (
91   IN VOID
92   )
93 {
94   UINT32     Data;
95 
96   /* enable MTCMOS for GPU */
97   MmioWrite32 (AO_CTRL_BASE + SC_PW_MTCMOS_EN0, PW_EN0_G3D);
98   do {
99     Data = MmioRead32 (AO_CTRL_BASE + SC_PW_MTCMOS_ACK_STAT0);
100   } while ((Data & PW_EN0_G3D) == 0);
101 }
102 
103 EFI_STATUS
HiKeyInitPeripherals(IN VOID)104 HiKeyInitPeripherals (
105   IN VOID
106   )
107 {
108   UINT32     Data, Bits;
109 
110   /* make I2C0/I2C1/I2C2/SPI0 out of reset */
111   Bits = PERIPH_RST3_I2C0 | PERIPH_RST3_I2C1 | PERIPH_RST3_I2C2 | \
112          PERIPH_RST3_SSP;
113   MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS3, Bits);
114 
115   do {
116     Data = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_RSTSTAT3);
117   } while (Data & Bits);
118 
119   UartInit ();
120   MtcmosInit ();
121 
122   /* Set DETECT_J15_FASTBOOT (GPIO24) pin as GPIO function */
123   MmioWrite32 (0xf7010950, 0);        /* configure GPIO24 as nopull */
124   MmioWrite32 (0xf7010140, 0);        /* configure GPIO24 as GPIO */
125 
126   return EFI_SUCCESS;
127 }
128 
129 EFI_STATUS
130 EFIAPI
AbootimgAppendKernelArgs(IN CHAR16 * Args,IN UINTN Size)131 AbootimgAppendKernelArgs (
132   IN CHAR16            *Args,
133   IN UINTN              Size
134   )
135 {
136   EFI_STATUS                  Status;
137   EFI_BLOCK_IO_PROTOCOL      *BlockIoProtocol;
138   VOID                       *DataPtr;
139   RANDOM_SERIAL_NUMBER       *RandomSN;
140   EFI_DEVICE_PATH_PROTOCOL   *FlashDevicePath;
141   EFI_HANDLE                  FlashHandle;
142 
143   if (Args == NULL) {
144     return EFI_INVALID_PARAMETER;
145   }
146   FlashDevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdAndroidFastbootNvmDevicePath));
147   Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &FlashDevicePath, &FlashHandle);
148   if (EFI_ERROR (Status)) {
149     DEBUG ((DEBUG_ERROR, "Warning: Couldn't locate Android NVM device (status: %r)\n", Status));
150     // Failing to locate partitions should not prevent to do other Android FastBoot actions
151     return EFI_SUCCESS;
152   }
153   Status = gBS->OpenProtocol (
154                   FlashHandle,
155                   &gEfiBlockIoProtocolGuid,
156                   (VOID **) &BlockIoProtocol,
157                   gImageHandle,
158                   NULL,
159                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
160                   );
161   if (EFI_ERROR (Status)) {
162     DEBUG ((DEBUG_WARN, "Warning: Couldn't open block device (status: %r)\n", Status));
163     return EFI_DEVICE_ERROR;
164   }
165 
166   DataPtr = AllocatePages (1);
167   if (DataPtr == NULL) {
168     return EFI_BUFFER_TOO_SMALL;
169   }
170   Status = BlockIoProtocol->ReadBlocks (
171                               BlockIoProtocol,
172                               BlockIoProtocol->Media->MediaId,
173                               SERIAL_NUMBER_LBA,
174                               SERIAL_NUMBER_BLOCK_SIZE,
175                               DataPtr
176                               );
177   if (EFI_ERROR (Status)) {
178     DEBUG ((DEBUG_WARN, "Warning: Failed on reading blocks\n"));
179     goto Exit;
180   }
181   RandomSN = (RANDOM_SERIAL_NUMBER *)DataPtr;
182   if (RandomSN->Magic != RANDOM_MAGIC) {
183     UnicodeSPrint(
184       RandomSN->UnicodeSN, SERIAL_NUMBER_SIZE * sizeof (CHAR16),
185       L"0123456789abcdef"
186       );
187   }
188   UnicodeSPrint (
189     Args + StrLen (Args), Size - StrLen (Args),
190     L" androidboot.serialno=%s",
191     RandomSN->UnicodeSN
192     );
193   FreePages (DataPtr, 1);
194   return EFI_SUCCESS;
195 Exit:
196   FreePages (DataPtr, 1);
197   return Status;
198 }
199 
200 EFI_STATUS
201 EFIAPI
AbootimgUpdateDtb(IN EFI_PHYSICAL_ADDRESS OrigFdtBase,OUT EFI_PHYSICAL_ADDRESS * NewFdtBase)202 AbootimgUpdateDtb (
203   IN  EFI_PHYSICAL_ADDRESS        OrigFdtBase,
204   OUT EFI_PHYSICAL_ADDRESS       *NewFdtBase
205   )
206 {
207   UINTN             FdtSize, NumPages;
208   INTN              err;
209   EFI_STATUS        Status;
210 
211   //
212   // Sanity checks on the original FDT blob.
213   //
214   err = fdt_check_header ((VOID*)(UINTN)OrigFdtBase);
215   if (err != 0) {
216     DEBUG ((DEBUG_ERROR, "ERROR: Device Tree header not valid (err:%d)\n", err));
217     return EFI_INVALID_PARAMETER;
218   }
219 
220   //
221   // Store the FDT as Runtime Service Data to prevent the Kernel from
222   // overwritting its data.
223   //
224   FdtSize = fdt_totalsize ((VOID *)(UINTN)OrigFdtBase);
225   NumPages = EFI_SIZE_TO_PAGES (FdtSize) + 20;
226   Status = gBS->AllocatePages (
227                   AllocateAnyPages, EfiRuntimeServicesData,
228                   NumPages, NewFdtBase);
229   if (EFI_ERROR (Status)) {
230     return EFI_BUFFER_TOO_SMALL;
231   }
232 
233   CopyMem (
234     (VOID*)(UINTN)*NewFdtBase,
235     (VOID*)(UINTN)OrigFdtBase,
236     FdtSize
237     );
238 
239   fdt_pack ((VOID*)(UINTN)*NewFdtBase);
240   err = fdt_check_header ((VOID*)(UINTN)*NewFdtBase);
241   if (err != 0) {
242     DEBUG ((DEBUG_ERROR, "ERROR: Device Tree header not valid (err:%d)\n", err));
243     gBS->FreePages (*NewFdtBase, NumPages);
244     return EFI_INVALID_PARAMETER;
245   }
246   return EFI_SUCCESS;
247 }
248 
249 ABOOTIMG_PROTOCOL mAbootimg = {
250   AbootimgAppendKernelArgs,
251   AbootimgUpdateDtb
252 };
253 
254 EFI_STATUS
255 EFIAPI
VirtualKeyboardRegister(IN VOID)256 VirtualKeyboardRegister (
257   IN VOID
258   )
259 {
260   EFI_STATUS           Status;
261 
262   Status = gBS->LocateProtocol (
263                   &gEmbeddedGpioProtocolGuid,
264                   NULL,
265                   (VOID **) &mGpio
266                   );
267   if (EFI_ERROR (Status)) {
268     return Status;
269   }
270   return EFI_SUCCESS;
271 }
272 
273 EFI_STATUS
274 EFIAPI
VirtualKeyboardReset(IN VOID)275 VirtualKeyboardReset (
276   IN VOID
277   )
278 {
279   EFI_STATUS           Status;
280 
281   if (mGpio == NULL) {
282     return EFI_INVALID_PARAMETER;
283   }
284   Status = mGpio->Set (mGpio, DETECT_J15_FASTBOOT, GPIO_MODE_INPUT);
285   return Status;
286 }
287 
288 BOOLEAN
289 EFIAPI
VirtualKeyboardQuery(IN VIRTUAL_KBD_KEY * VirtualKey)290 VirtualKeyboardQuery (
291   IN VIRTUAL_KBD_KEY             *VirtualKey
292   )
293 {
294   EFI_STATUS           Status;
295   UINTN                Value = 0;
296 
297   if ((VirtualKey == NULL) || (mGpio == NULL)) {
298     return FALSE;
299   }
300   if (MmioRead32 (ADB_REBOOT_ADDRESS) == ADB_REBOOT_BOOTLOADER) {
301     goto Done;
302   } else {
303     Status = mGpio->Get (mGpio, DETECT_J15_FASTBOOT, &Value);
304     if (EFI_ERROR (Status) || (Value != 0)) {
305       return FALSE;
306     }
307   }
308 Done:
309   VirtualKey->Signature = VIRTUAL_KEYBOARD_KEY_SIGNATURE;
310   VirtualKey->Key.ScanCode = SCAN_NULL;
311   VirtualKey->Key.UnicodeChar = L'f';
312   return TRUE;
313 }
314 
315 EFI_STATUS
316 EFIAPI
VirtualKeyboardClear(IN VIRTUAL_KBD_KEY * VirtualKey)317 VirtualKeyboardClear (
318   IN VIRTUAL_KBD_KEY            *VirtualKey
319   )
320 {
321   if (VirtualKey == NULL) {
322     return EFI_INVALID_PARAMETER;
323   }
324   if (MmioRead32 (ADB_REBOOT_ADDRESS) == ADB_REBOOT_BOOTLOADER) {
325     MmioWrite32 (ADB_REBOOT_ADDRESS, ADB_REBOOT_NONE);
326     WriteBackInvalidateDataCacheRange ((VOID *)ADB_REBOOT_ADDRESS, 4);
327   }
328   return EFI_SUCCESS;
329 }
330 
331 PLATFORM_VIRTUAL_KBD_PROTOCOL mVirtualKeyboard = {
332   VirtualKeyboardRegister,
333   VirtualKeyboardReset,
334   VirtualKeyboardQuery,
335   VirtualKeyboardClear
336 };
337 
338 EFI_STATUS
339 EFIAPI
HiKeyEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)340 HiKeyEntryPoint (
341   IN EFI_HANDLE         ImageHandle,
342   IN EFI_SYSTEM_TABLE   *SystemTable
343   )
344 {
345   EFI_STATUS            Status;
346 
347   Status = HiKeyInitPeripherals ();
348   if (EFI_ERROR (Status)) {
349     return Status;
350   }
351 
352   // RegisterNonDicoverableMmioDevice
353   Status = RegisterNonDiscoverableMmioDevice (
354              NonDiscoverableDeviceTypeSdhci,
355              NonDiscoverableDeviceDmaTypeNonCoherent,
356              NULL,
357              NULL,
358              1,
359              0xF723D000, // eMMC
360              SIZE_4KB
361              );
362   if (EFI_ERROR (Status)) {
363     return Status;
364   }
365   Status = RegisterNonDiscoverableMmioDevice (
366              NonDiscoverableDeviceTypeSdhci,
367              NonDiscoverableDeviceDmaTypeNonCoherent,
368              NULL,
369              NULL,
370              1,
371              0xF723E000, // SD
372              SIZE_4KB
373              );
374   if (EFI_ERROR (Status)) {
375     return Status;
376   }
377 
378   Status = gBS->InstallProtocolInterface (
379                   &ImageHandle,
380                   &gAbootimgProtocolGuid,
381                   EFI_NATIVE_INTERFACE,
382                   &mAbootimg
383                   );
384   if (EFI_ERROR (Status)) {
385     return Status;
386   }
387 
388   Status = gBS->InstallProtocolInterface (
389                   &ImageHandle,
390                   &gPlatformVirtualKeyboardProtocolGuid,
391                   EFI_NATIVE_INTERFACE,
392                   &mVirtualKeyboard
393                   );
394   return Status;
395 }
396