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