1 /** @file 2 * 3 * Copyright (c) 2015, Linaro Ltd. All rights reserved. 4 * Copyright (c) 2015, 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/BdsLib.h> 18 #include <Library/CacheMaintenanceLib.h> 19 #include <Library/DevicePathLib.h> 20 #include <Library/DxeServicesLib.h> 21 #include <Library/IoLib.h> 22 #include <Library/MemoryAllocationLib.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/BlockIo.h> 29 #include <Protocol/DevicePathFromText.h> 30 #include <Protocol/DevicePathToText.h> 31 #include <Protocol/DwUsb.h> 32 #include <Protocol/EmbeddedGpio.h> 33 #include <Protocol/SimpleFileSystem.h> 34 35 #include <Guid/Fdt.h> 36 #include <Guid/FileInfo.h> 37 #include <Guid/EventGroup.h> 38 #include <Guid/GlobalVariable.h> 39 #include <Guid/HiKeyVariable.h> 40 #include <Guid/VariableFormat.h> 41 42 #include "HiKeyDxeInternal.h" 43 44 typedef enum { 45 HIKEY_DTB_ANDROID = 0, /* DTB is attached at the end of boot.img */ 46 HIKEY_DTB_LINUX = 1, /* DTB is in partition */ 47 HIKEY_DTB_SD = 2, /* DTB is already in SD Card */ 48 } HiKeyDtbType; 49 50 #define HIKEY_IO_BLOCK_SIZE 512 51 52 #define MAX_BOOT_ENTRIES 16 53 // Jumper on pin5-6 of J15 determines whether boot to fastboot 54 #define DETECT_J15_FASTBOOT 24 // GPIO 3_0 55 56 #define USER_LED1 32 // GPIO 4_0 57 #define USER_LED2 33 // GPIO 4_1 58 #define USER_LED3 34 // GPIO 4_2 59 #define USER_LED4 35 // GPIO 4_3 60 61 struct HiKeyBootEntry { 62 CHAR16 *Path; 63 CHAR16 *Args; 64 CHAR16 *Description; 65 UINT16 LoadType; 66 }; 67 68 STATIC CONST BOOLEAN mIsEndOfDxeEvent = TRUE; 69 STATIC UINT16 *mBootOrder = NULL; 70 STATIC UINT16 mBootCount = 0; 71 STATIC UINT16 mBootIndex = 0; 72 73 #define HIKEY_BOOT_ENTRY_FASTBOOT 0 74 #define HIKEY_BOOT_ENTRY_BOOT_EMMC 1 /* boot from eMMC */ 75 #define HIKEY_BOOT_ENTRY_BOOT_SD 2 /* boot from SD card */ 76 77 STATIC struct HiKeyBootEntry LinuxEntries[] = { 78 [HIKEY_BOOT_ENTRY_FASTBOOT] = { 79 L"FvFile(9588502a-5370-11e3-8631-d7c5951364c8)", 80 //L"VenHw(B549F005-4BD4-4020-A0CB-06F42BDA68C3)/HD(6,GPT,5C0F213C-17E1-4149-88C8-8B50FB4EC70E,0x7000,0x20000)/\\EFI\\BOOT\\FASTBOOT.EFI", 81 NULL, 82 L"fastboot", 83 LOAD_OPTION_CATEGORY_APP 84 }, 85 [HIKEY_BOOT_ENTRY_BOOT_EMMC] = { 86 L"VenHw(B549F005-4BD4-4020-A0CB-06F42BDA68C3)/HD(6,GPT,5C0F213C-17E1-4149-88C8-8B50FB4EC70E,0x7000,0x20000)/\\EFI\\BOOT\\GRUBAA64.EFI", 87 NULL, 88 L"boot from eMMC", 89 LOAD_OPTION_CATEGORY_APP 90 }, 91 [HIKEY_BOOT_ENTRY_BOOT_SD] = { 92 L"VenHw(594BFE73-5E18-4F12-8119-19DB8C5FC849)/HD(1,MBR,0x00000000,0x3F,0x21FC0)/\\EFI\\BOOT\\BOOTAA64.EFI", 93 NULL, 94 L"boot from SD card", 95 LOAD_OPTION_CATEGORY_BOOT 96 } 97 }; 98 99 STATIC struct HiKeyBootEntry AndroidEntries[] = { 100 [HIKEY_BOOT_ENTRY_FASTBOOT] = { 101 L"FvFile(9588502a-5370-11e3-8631-d7c5951364c8)", 102 //L"VenHw(B549F005-4BD4-4020-A0CB-06F42BDA68C3)/HD(6,GPT,5C0F213C-17E1-4149-88C8-8B50FB4EC70E,0x7000,0x20000)/\\EFI\\BOOT\\FASTBOOT.EFI", 103 NULL, 104 L"fastboot", 105 LOAD_OPTION_CATEGORY_APP 106 }, 107 [HIKEY_BOOT_ENTRY_BOOT_EMMC] = { 108 L"VenHw(B549F005-4BD4-4020-A0CB-06F42BDA68C3)/HD(6,GPT,5C0F213C-17E1-4149-88C8-8B50FB4EC70E,0x7000,0x20000)/Offset(0x0000,0x20000)", 109 L"console=ttyAMA3,115200 earlycon=pl011,0xf7113000 root=/dev/mmcblk0p9 rw rootwait efi=noruntime", 110 L"boot from eMMC", 111 LOAD_OPTION_CATEGORY_BOOT 112 }, 113 [HIKEY_BOOT_ENTRY_BOOT_SD] = { 114 L"VenHw(594BFE73-5E18-4F12-8119-19DB8C5FC849)/HD(1,MBR,0x00000000,0x3F,0x21FC0)/Image", 115 L"dtb=hi6220-hikey.dtb console=ttyAMA3,115200 earlycon=pl011,0xf7113000 root=/dev/mmcblk1p2 rw rootwait initrd=initrd.img efi=noruntime", 116 L"boot from SD card", 117 LOAD_OPTION_CATEGORY_BOOT 118 } 119 }; 120 121 122 STATIC 123 BOOLEAN 124 EFIAPI 125 HiKeyVerifyBootEntry ( 126 IN CHAR16 *BootVariableName, 127 IN CHAR16 *BootDevicePathText, 128 IN CHAR16 *BootArgs, 129 IN CHAR16 *BootDescription, 130 IN UINT16 LoadOptionAttr 131 ) 132 { 133 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathToTextProtocol; 134 CHAR16 *DevicePathText; 135 UINTN EfiLoadOptionSize; 136 EFI_LOAD_OPTION *EfiLoadOption; 137 BDS_LOAD_OPTION *LoadOption; 138 EFI_STATUS Status; 139 UINTN DescriptionLength; 140 141 Status = GetGlobalEnvironmentVariable (BootVariableName, NULL, &EfiLoadOptionSize, (VOID**)&EfiLoadOption); 142 if (EFI_ERROR (Status)) { 143 return FALSE; 144 } 145 if (EfiLoadOption == NULL) { 146 return FALSE; 147 } 148 if (EfiLoadOptionSize < sizeof(UINT32) + sizeof(UINT16) + sizeof(CHAR16) + sizeof(EFI_DEVICE_PATH_PROTOCOL)) { 149 return FALSE; 150 } 151 LoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION)); 152 if (LoadOption == NULL) { 153 return FALSE; 154 } 155 156 LoadOption->LoadOption = EfiLoadOption; 157 LoadOption->Attributes = *(UINT32*)EfiLoadOption; 158 LoadOption->FilePathListLength = *(UINT16*)(EfiLoadOption + sizeof(UINT32)); 159 LoadOption->Description = (CHAR16*)(EfiLoadOption + sizeof(UINT32) + sizeof(UINT16)); 160 DescriptionLength = StrSize (LoadOption->Description); 161 LoadOption->FilePathList = (EFI_DEVICE_PATH_PROTOCOL*)(EfiLoadOption + sizeof(UINT32) + sizeof(UINT16) + DescriptionLength); 162 if ((UINTN)((UINTN)LoadOption->FilePathList + LoadOption->FilePathListLength - (UINTN)EfiLoadOption) == EfiLoadOptionSize) { 163 LoadOption->OptionalData = NULL; 164 LoadOption->OptionalDataSize = 0; 165 } else { 166 LoadOption->OptionalData = (VOID*)((UINTN)(LoadOption->FilePathList) + LoadOption->FilePathListLength); 167 LoadOption->OptionalDataSize = EfiLoadOptionSize - ((UINTN)LoadOption->OptionalData - (UINTN)EfiLoadOption); 168 } 169 170 if (((BootArgs == NULL) && (LoadOption->OptionalDataSize)) || 171 (BootArgs && (LoadOption->OptionalDataSize == 0))) { 172 return FALSE; 173 } else if (BootArgs && LoadOption->OptionalDataSize) { 174 if (StrCmp (BootArgs, LoadOption->OptionalData) != 0) 175 return FALSE; 176 } 177 if ((LoadOption->Description == NULL) || (BootDescription == NULL)) { 178 return FALSE; 179 } 180 if (StrCmp (BootDescription, LoadOption->Description) != 0) { 181 return FALSE; 182 } 183 if ((LoadOption->Attributes & LOAD_OPTION_CATEGORY) != (LoadOptionAttr & LOAD_OPTION_CATEGORY)) { 184 return FALSE; 185 } 186 187 Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); 188 ASSERT_EFI_ERROR(Status); 189 DevicePathText = DevicePathToTextProtocol->ConvertDevicePathToText(LoadOption->FilePathList, TRUE, TRUE); 190 if (StrCmp (DevicePathText, BootDevicePathText) != 0) { 191 return FALSE; 192 } 193 194 FreePool (LoadOption); 195 return TRUE; 196 } 197 198 STATIC 199 EFI_STATUS 200 EFIAPI 201 HiKeyCreateBootEntry ( 202 IN CHAR16 *DevicePathText, 203 IN CHAR16 *BootArgs, 204 IN CHAR16 *BootDescription, 205 IN UINT16 LoadOption 206 ) 207 { 208 BDS_LOAD_OPTION *BdsLoadOption; 209 EFI_STATUS Status; 210 UINTN DescriptionSize; 211 UINTN BootOrderSize; 212 CHAR16 BootVariableName[9]; 213 UINT8 *EfiLoadOptionPtr; 214 EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; 215 UINTN NodeLength; 216 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *DevicePathFromTextProtocol; 217 218 if ((DevicePathText == NULL) || (BootDescription == NULL)) { 219 DEBUG ((EFI_D_ERROR, "%a: Invalid Parameters\n", __func__)); 220 return EFI_INVALID_PARAMETER; 221 } 222 223 UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", mBootCount); 224 if (HiKeyVerifyBootEntry (BootVariableName, DevicePathText, BootArgs, BootDescription, LoadOption) == TRUE) { 225 // The boot entry is already created. 226 Status = EFI_SUCCESS; 227 goto done; 228 } 229 230 BdsLoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION)); 231 ASSERT (BdsLoadOption != NULL); 232 233 Status = gBS->LocateProtocol ( 234 &gEfiDevicePathFromTextProtocolGuid, 235 NULL, 236 (VOID**)&DevicePathFromTextProtocol 237 ); 238 ASSERT_EFI_ERROR(Status); 239 240 BdsLoadOption->FilePathList = DevicePathFromTextProtocol->ConvertTextToDevicePath (DevicePathText); 241 ASSERT (BdsLoadOption->FilePathList != NULL); 242 BdsLoadOption->FilePathListLength = GetDevicePathSize (BdsLoadOption->FilePathList); 243 BdsLoadOption->Attributes = LOAD_OPTION_ACTIVE | (LoadOption & LOAD_OPTION_CATEGORY); 244 245 if (BootArgs) { 246 /* Always force the BootArgs to save 512 characters. */ 247 ASSERT (StrSize(BootArgs) <= 512); 248 BdsLoadOption->OptionalDataSize = 512; 249 BdsLoadOption->OptionalData = (CHAR16*)AllocateZeroPool (BdsLoadOption->OptionalDataSize); 250 ASSERT (BdsLoadOption->OptionalData != NULL); 251 StrCpy (BdsLoadOption->OptionalData, BootArgs); 252 } 253 254 BdsLoadOption->LoadOptionIndex = mBootCount; 255 DescriptionSize = StrSize (BootDescription); 256 BdsLoadOption->Description = (VOID*)AllocateZeroPool (DescriptionSize); 257 StrCpy (BdsLoadOption->Description, BootDescription); 258 259 BdsLoadOption->LoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + DescriptionSize + BdsLoadOption->FilePathListLength + BdsLoadOption->OptionalDataSize; 260 BdsLoadOption->LoadOption = (EFI_LOAD_OPTION*)AllocateZeroPool (BdsLoadOption->LoadOptionSize); 261 ASSERT (BdsLoadOption->LoadOption != NULL); 262 263 EfiLoadOptionPtr = (VOID*)BdsLoadOption->LoadOption; 264 265 // 266 // Populate the EFI Load Option and BDS Boot Option structures 267 // 268 269 // Attributes fields 270 *(UINT32*)EfiLoadOptionPtr = BdsLoadOption->Attributes; 271 EfiLoadOptionPtr += sizeof(UINT32); 272 273 // FilePath List fields 274 *(UINT16*)EfiLoadOptionPtr = BdsLoadOption->FilePathListLength; 275 EfiLoadOptionPtr += sizeof(UINT16); 276 277 // Boot description fields 278 CopyMem (EfiLoadOptionPtr, BdsLoadOption->Description, DescriptionSize); 279 EfiLoadOptionPtr += DescriptionSize; 280 281 // File path fields 282 DevicePathNode = BdsLoadOption->FilePathList; 283 while (!IsDevicePathEndType (DevicePathNode)) { 284 NodeLength = DevicePathNodeLength(DevicePathNode); 285 CopyMem (EfiLoadOptionPtr, DevicePathNode, NodeLength); 286 EfiLoadOptionPtr += NodeLength; 287 DevicePathNode = NextDevicePathNode (DevicePathNode); 288 } 289 290 // Set the End Device Path Type 291 SetDevicePathEndNode (EfiLoadOptionPtr); 292 EfiLoadOptionPtr += sizeof(EFI_DEVICE_PATH); 293 294 // Fill the Optional Data 295 if (BdsLoadOption->OptionalDataSize > 0) { 296 CopyMem (EfiLoadOptionPtr, BdsLoadOption->OptionalData, BdsLoadOption->OptionalDataSize); 297 } 298 299 Status = gRT->SetVariable ( 300 BootVariableName, 301 &gEfiGlobalVariableGuid, 302 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 303 BdsLoadOption->LoadOptionSize, 304 BdsLoadOption->LoadOption 305 ); 306 if (EFI_ERROR (Status)) { 307 DEBUG ((EFI_D_ERROR, "%a: failed to set BootVariable\n", __func__)); 308 return Status; 309 } 310 311 done: 312 BootOrderSize = mBootCount * sizeof (UINT16); 313 mBootOrder = ReallocatePool (BootOrderSize, BootOrderSize + sizeof (UINT16), mBootOrder); 314 mBootOrder[mBootCount] = mBootCount; 315 mBootCount++; 316 return Status; 317 } 318 319 STATIC 320 EFI_STATUS 321 EFIAPI 322 HiKeyCreateBootOrder ( 323 IN VOID 324 ) 325 { 326 UINT16 *BootOrder; 327 UINTN BootOrderSize; 328 UINTN Index; 329 EFI_STATUS Status; 330 331 Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder); 332 if (EFI_ERROR(Status) == 0) { 333 if (BootOrderSize == mBootCount) { 334 for (Index = 0; Index < mBootCount; Index++) { 335 if (BootOrder[Index] != mBootOrder[Index]) { 336 break; 337 } 338 } 339 if (Index == mBootCount) { 340 // Found BootOrder variable with expected value. 341 return EFI_SUCCESS; 342 } 343 } 344 } 345 346 Status = gRT->SetVariable ( 347 (CHAR16*)L"BootOrder", 348 &gEfiGlobalVariableGuid, 349 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 350 mBootCount * sizeof(UINT16), 351 mBootOrder 352 ); 353 return Status; 354 } 355 356 STATIC 357 EFI_STATUS 358 EFIAPI 359 HiKeyCreateBootNext ( 360 IN VOID 361 ) 362 { 363 EFI_STATUS Status; 364 UINT16 *BootNext; 365 UINTN BootNextSize; 366 367 BootNextSize = sizeof(UINT16); 368 Status = GetGlobalEnvironmentVariable (L"BootNext", NULL, &BootNextSize, (VOID**)&BootNext); 369 if (EFI_ERROR(Status) == 0) { 370 if (BootNextSize == sizeof (UINT16)) { 371 if (*BootNext == mBootOrder[mBootIndex]) { 372 // Found the BootNext variable with expected value. 373 return EFI_SUCCESS; 374 } 375 } 376 } 377 BootNext = &mBootOrder[mBootIndex]; 378 Status = gRT->SetVariable ( 379 (CHAR16*)L"BootNext", 380 &gEfiGlobalVariableGuid, 381 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 382 sizeof (UINT16), 383 BootNext 384 ); 385 return Status; 386 } 387 388 STATIC 389 VOID 390 EFIAPI 391 HiKeyTestLed ( 392 IN EMBEDDED_GPIO *Gpio 393 ) 394 { 395 EFI_STATUS Status; 396 397 Status = Gpio->Set (Gpio, USER_LED1, GPIO_MODE_OUTPUT_0); 398 if (EFI_ERROR (Status)) { 399 DEBUG ((EFI_D_ERROR, "%a: failed to set LED1\n", __func__)); 400 return; 401 } 402 Status = Gpio->Set (Gpio, USER_LED2, GPIO_MODE_OUTPUT_1); 403 if (EFI_ERROR (Status)) { 404 DEBUG ((EFI_D_ERROR, "%a: failed to set LED2\n", __func__)); 405 return; 406 } 407 Status = Gpio->Set (Gpio, USER_LED3, GPIO_MODE_OUTPUT_0); 408 if (EFI_ERROR (Status)) { 409 DEBUG ((EFI_D_ERROR, "%a: failed to set LED3\n", __func__)); 410 return; 411 } 412 Status = Gpio->Set (Gpio, USER_LED4, GPIO_MODE_OUTPUT_1); 413 if (EFI_ERROR (Status)) { 414 DEBUG ((EFI_D_ERROR, "%a: failed to set LED4\n", __func__)); 415 return; 416 } 417 } 418 419 420 #define REBOOT_REASON_ADDR 0x05F01000 421 #define REBOOT_REASON_BOOTLOADER 0x77665500 422 #define REBOOT_REASON_NONE 0x77665501 423 STATIC 424 BOOLEAN 425 EFIAPI 426 HiKeyDetectRebootReason ( 427 IN VOID 428 ) 429 { 430 UINT32 *addr = (UINT32*)REBOOT_REASON_ADDR; 431 UINT32 val; 432 433 val = *addr; 434 /* Write NONE to the reason address to clear the state */ 435 *addr = REBOOT_REASON_NONE; 436 /* Check to see if "reboot booloader" was specified */ 437 if (val == REBOOT_REASON_BOOTLOADER) 438 return TRUE; 439 440 return FALSE; 441 } 442 443 STATIC 444 BOOLEAN 445 EFIAPI 446 HiKeyIsJumperConnected ( 447 IN VOID 448 ) 449 { 450 EMBEDDED_GPIO *Gpio; 451 EFI_STATUS Status; 452 UINTN Value; 453 454 Status = gBS->LocateProtocol (&gEmbeddedGpioProtocolGuid, NULL, (VOID **)&Gpio); 455 ASSERT_EFI_ERROR (Status); 456 457 Status = Gpio->Set (Gpio, DETECT_J15_FASTBOOT, GPIO_MODE_INPUT); 458 if (EFI_ERROR (Status)) { 459 DEBUG ((EFI_D_ERROR, "%a: failed to set jumper as gpio input\n", __func__)); 460 return FALSE; 461 } 462 Status = Gpio->Get (Gpio, DETECT_J15_FASTBOOT, &Value); 463 if (EFI_ERROR (Status)) { 464 DEBUG ((EFI_D_ERROR, "%a: failed to get value from jumper\n", __func__)); 465 return FALSE; 466 } 467 468 HiKeyTestLed (Gpio); 469 if (Value != 0) 470 return FALSE; 471 return TRUE; 472 } 473 474 STATIC 475 BOOLEAN 476 EFIAPI 477 HiKeySDCardIsPresent ( 478 IN VOID 479 ) 480 { 481 UINT32 Value; 482 483 /* 484 * FIXME 485 * At first, reading GPIO pin shouldn't exist in SD driver. We need to 486 * add some callbacks to handle settings for hardware platform. 487 * In the second, reading GPIO pin should be based on GPIO driver. Now 488 * GPIO driver could only be used for one PL061 gpio controller. And it's 489 * used to detect jumper setting. As a workaround, we have to read the gpio 490 * register instead at here. 491 * 492 */ 493 Value = MmioRead32 (0xf8012000 + (1 << 2)); 494 if (Value) 495 return FALSE; 496 return TRUE; 497 } 498 499 #define BOOT_MAGIC "ANDROID!" 500 #define BOOT_MAGIC_LENGTH sizeof (BOOT_MAGIC) - 1 501 502 /* 503 * Check which boot type is valid for eMMC. 504 */ 505 STATIC 506 EFI_STATUS 507 EFIAPI 508 HiKeyCheckEmmcDtbType ( 509 OUT UINTN *DtbType 510 ) 511 { 512 EFI_DEVICE_PATH_PROTOCOL *BlockDevicePath; 513 EFI_BLOCK_IO_PROTOCOL *BlockIoProtocol; 514 EFI_HANDLE Handle; 515 EFI_STATUS Status; 516 VOID *DataPtr, *AlignedPtr; 517 518 /* Check boot image */ 519 BlockDevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdBootImagePath)); 520 Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &BlockDevicePath, &Handle); 521 ASSERT_EFI_ERROR (Status); 522 523 Status = gBS->OpenProtocol ( 524 Handle, 525 &gEfiBlockIoProtocolGuid, 526 (VOID **) &BlockIoProtocol, 527 gImageHandle, 528 NULL, 529 EFI_OPEN_PROTOCOL_GET_PROTOCOL 530 ); 531 ASSERT_EFI_ERROR (Status); 532 533 /* Read the header of boot image. */ 534 DataPtr = AllocateZeroPool (HIKEY_IO_BLOCK_SIZE * 2); 535 ASSERT (DataPtr != 0); 536 AlignedPtr = (VOID *)(((UINTN)DataPtr + HIKEY_IO_BLOCK_SIZE - 1) & ~(HIKEY_IO_BLOCK_SIZE - 1)); 537 InvalidateDataCacheRange (AlignedPtr, HIKEY_IO_BLOCK_SIZE); 538 /* TODO: Update 0x7000 by LBA what is fetched from partition. */ 539 Status = BlockIoProtocol->ReadBlocks (BlockIoProtocol, BlockIoProtocol->Media->MediaId, 540 0x7000, HIKEY_IO_BLOCK_SIZE, AlignedPtr); 541 ASSERT_EFI_ERROR (Status); 542 if (AsciiStrnCmp ((CHAR8 *)AlignedPtr, BOOT_MAGIC, BOOT_MAGIC_LENGTH) != 0) { 543 /* It's debian boot image. */ 544 *DtbType = HIKEY_DTB_LINUX; 545 } else { 546 /* It's android boot image. */ 547 *DtbType = HIKEY_DTB_ANDROID; 548 } 549 FreePool (DataPtr); 550 return Status; 551 } 552 553 STATIC 554 BOOLEAN 555 EFIAPI 556 HiKeyIsSdBoot ( 557 IN struct HiKeyBootEntry *Entry 558 ) 559 { 560 CHAR16 *Path; 561 EFI_DEVICE_PATH *DevicePath, *NextDevicePath; 562 EFI_STATUS Status; 563 EFI_HANDLE Handle; 564 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FsProtocol; 565 EFI_FILE_PROTOCOL *Fs; 566 EFI_FILE_INFO *FileInfo; 567 EFI_FILE_PROTOCOL *File; 568 FILEPATH_DEVICE_PATH *FilePathDevicePath; 569 UINTN Index, Size; 570 UINTN HandleCount; 571 EFI_HANDLE *HandleBuffer; 572 EFI_DEVICE_PATH_PROTOCOL *DevicePathProtocol; 573 BOOLEAN Found = FALSE, Result = FALSE; 574 575 if (HiKeySDCardIsPresent () == FALSE) 576 return FALSE; 577 Path = Entry[HIKEY_BOOT_ENTRY_BOOT_SD].Path; 578 ASSERT (Path != NULL); 579 580 DevicePath = ConvertTextToDevicePath (Path); 581 if (DevicePath == NULL) { 582 DEBUG ((EFI_D_ERROR, "Warning: Couldn't get device path\n")); 583 return FALSE; 584 } 585 586 /* Connect handles to drivers. Since simple filesystem driver is loaded later by default. */ 587 do { 588 // Locate all the driver handles 589 Status = gBS->LocateHandleBuffer ( 590 AllHandles, 591 NULL, 592 NULL, 593 &HandleCount, 594 &HandleBuffer 595 ); 596 if (EFI_ERROR (Status)) { 597 break; 598 } 599 600 // Connect every handles 601 for (Index = 0; Index < HandleCount; Index++) { 602 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); 603 } 604 605 if (HandleBuffer != NULL) { 606 FreePool (HandleBuffer); 607 } 608 609 // Check if new handles have been created after the start of the previous handles 610 Status = gDS->Dispatch (); 611 } while (!EFI_ERROR(Status)); 612 613 // List all the Simple File System Protocols 614 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandleCount, &HandleBuffer); 615 if (EFI_ERROR (Status)) { 616 DEBUG ((EFI_D_ERROR, "Warning: Failed to list all the simple filesystem protocols (status:%r)\n", Status)); 617 return FALSE; 618 } 619 for (Index = 0; Index < HandleCount; Index++) { 620 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol); 621 if (EFI_ERROR(Status)) 622 continue; 623 NextDevicePath = NextDevicePathNode (DevicePath); 624 Size = (UINTN)NextDevicePath - (UINTN)DevicePath; 625 if (Size <= GetDevicePathSize (DevicePath)) { 626 if ((CompareMem (DevicePath, DevicePathProtocol, Size)) == 0) { 627 Found = TRUE; 628 break; 629 } 630 } 631 } 632 if (!Found) { 633 DEBUG ((EFI_D_ERROR, "Warning: Failed to find valid device path\n")); 634 return FALSE; 635 } 636 637 Handle = HandleBuffer[Index]; 638 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &Handle); 639 if (EFI_ERROR (Status)) { 640 DEBUG ((EFI_D_ERROR, "Warning: Couldn't locate device (status: %r)\n", Status)); 641 return FALSE; 642 } 643 FilePathDevicePath = (FILEPATH_DEVICE_PATH*)DevicePath; 644 645 Status = gBS->OpenProtocol ( 646 Handle, 647 &gEfiSimpleFileSystemProtocolGuid, 648 (VOID**)&FsProtocol, 649 gImageHandle, 650 Handle, 651 EFI_OPEN_PROTOCOL_BY_DRIVER 652 ); 653 if (EFI_ERROR (Status)) { 654 DEBUG ((EFI_D_ERROR, "Warning: Failedn't to mount as Simple Filrsystem (status: %r)\n", Status)); 655 return FALSE; 656 } 657 Status = FsProtocol->OpenVolume (FsProtocol, &Fs); 658 if (EFI_ERROR (Status)) { 659 goto CLOSE_PROTOCOL; 660 } 661 662 Status = Fs->Open (Fs, &File, FilePathDevicePath->PathName, EFI_FILE_MODE_READ, 0); 663 if (EFI_ERROR (Status)) { 664 goto CLOSE_PROTOCOL; 665 } 666 667 Size = 0; 668 File->GetInfo (File, &gEfiFileInfoGuid, &Size, NULL); 669 FileInfo = AllocatePool (Size); 670 Status = File->GetInfo (File, &gEfiFileInfoGuid, &Size, FileInfo); 671 if (EFI_ERROR (Status)) { 672 goto CLOSE_FILE; 673 } 674 675 // Get the file size 676 Size = FileInfo->FileSize; 677 FreePool (FileInfo); 678 if (Size != 0) { 679 Result = TRUE; 680 } 681 682 CLOSE_FILE: 683 File->Close (File); 684 CLOSE_PROTOCOL: 685 gBS->CloseProtocol ( 686 Handle, 687 &gEfiSimpleFileSystemProtocolGuid, 688 gImageHandle, 689 Handle); 690 return Result; 691 } 692 693 STATIC 694 EFI_STATUS 695 EFIAPI 696 HiKeyInstallFdt ( 697 VOID 698 ) 699 { 700 EFI_STATUS Status; 701 VOID *Image; 702 UINTN ImageSize, NumPages; 703 EFI_GUID *Guid; 704 EFI_PHYSICAL_ADDRESS FdtConfigurationTableBase; 705 706 Guid = &gHiKeyTokenSpaceGuid; 707 Status = GetSectionFromAnyFv (Guid, EFI_SECTION_RAW, 0, &Image, &ImageSize); 708 if (EFI_ERROR (Status)) 709 return Status; 710 NumPages = EFI_SIZE_TO_PAGES (ImageSize); 711 Status = gBS->AllocatePages ( 712 AllocateAnyPages, EfiRuntimeServicesData, 713 NumPages, &FdtConfigurationTableBase 714 ); 715 if (EFI_ERROR (Status)) 716 return Status; 717 CopyMem ((VOID *)(UINTN)FdtConfigurationTableBase, Image, ImageSize); 718 Status = gBS->InstallConfigurationTable ( 719 &gFdtTableGuid, 720 (VOID *)(UINTN)FdtConfigurationTableBase 721 ); 722 if (EFI_ERROR (Status)) { 723 gBS->FreePages (FdtConfigurationTableBase, NumPages); 724 } 725 return Status; 726 } 727 728 STATIC 729 VOID 730 EFIAPI 731 HiKeyOnEndOfDxe ( 732 EFI_EVENT Event, 733 VOID *Context 734 ) 735 { 736 EFI_STATUS Status; 737 UINTN VariableSize; 738 UINT16 AutoBoot, Count, Index; 739 UINTN DtbType; 740 struct HiKeyBootEntry *Entry; 741 742 VariableSize = sizeof (UINT16); 743 Status = gRT->GetVariable ( 744 (CHAR16 *)L"HiKeyAutoBoot", 745 &gHiKeyVariableGuid, 746 NULL, 747 &VariableSize, 748 (VOID*)&AutoBoot 749 ); 750 if (Status == EFI_NOT_FOUND) { 751 AutoBoot = 1; 752 Status = gRT->SetVariable ( 753 (CHAR16*)L"HiKeyAutoBoot", 754 &gHiKeyVariableGuid, 755 EFI_VARIABLE_NON_VOLATILE | 756 EFI_VARIABLE_BOOTSERVICE_ACCESS | 757 EFI_VARIABLE_RUNTIME_ACCESS, 758 sizeof (UINT16), 759 &AutoBoot 760 ); 761 ASSERT_EFI_ERROR (Status); 762 } else if (EFI_ERROR (Status) == 0) { 763 if (AutoBoot == 0) { 764 // Select boot entry by manual. 765 // Delete the BootNext environment variable 766 gRT->SetVariable (L"BootNext", 767 &gEfiGlobalVariableGuid, 768 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 769 0, 770 NULL); 771 return; 772 } 773 } 774 775 Status = HiKeyCheckEmmcDtbType (&DtbType); 776 ASSERT_EFI_ERROR (Status); 777 778 mBootCount = 0; 779 mBootOrder = NULL; 780 781 if (DtbType == HIKEY_DTB_LINUX) { 782 Count = sizeof (LinuxEntries) / sizeof (struct HiKeyBootEntry); 783 Entry = LinuxEntries; 784 } else if (DtbType == HIKEY_DTB_ANDROID) { 785 Count = sizeof (AndroidEntries) / sizeof (struct HiKeyBootEntry); 786 Entry = AndroidEntries; 787 } else { 788 ASSERT (0); 789 } 790 ASSERT (HIKEY_DTB_SD < Count); 791 if (HiKeyIsSdBoot (Entry) == TRUE) 792 DtbType = HIKEY_DTB_SD; 793 794 for (Index = 0; Index < Count; Index++) { 795 Status = HiKeyCreateBootEntry ( 796 Entry->Path, 797 Entry->Args, 798 Entry->Description, 799 Entry->LoadType 800 ); 801 ASSERT_EFI_ERROR (Status); 802 Entry++; 803 } 804 805 if ((mBootCount == 0) || (mBootCount >= MAX_BOOT_ENTRIES)) { 806 DEBUG ((EFI_D_ERROR, "%a: can't create boot entries\n", __func__)); 807 return; 808 } 809 810 Status = HiKeyCreateBootOrder (); 811 if (EFI_ERROR (Status)) { 812 DEBUG ((EFI_D_ERROR, "%a: failed to set BootOrder variable\n", __func__)); 813 return; 814 } 815 816 if (DtbType == HIKEY_DTB_SD) { 817 mBootIndex = HIKEY_BOOT_ENTRY_BOOT_SD; 818 } else { 819 mBootIndex = HIKEY_BOOT_ENTRY_BOOT_EMMC; 820 } 821 822 if (HiKeyGetUsbMode () == USB_DEVICE_MODE) { 823 if (HiKeyIsJumperConnected () == TRUE) 824 mBootIndex = HIKEY_BOOT_ENTRY_FASTBOOT; 825 /* Set mBootIndex as HIKEY_BOOT_ENTRY_FASTBOOT if adb reboot-bootloader is specified */ 826 if (HiKeyDetectRebootReason () == TRUE) 827 mBootIndex = HIKEY_BOOT_ENTRY_FASTBOOT; 828 } 829 830 Status = HiKeyCreateBootNext (); 831 if (EFI_ERROR (Status)) { 832 DEBUG ((EFI_D_ERROR, "%a: failed to set BootNext variable\n", __func__)); 833 return; 834 } 835 836 /* 837 * Priority of Loading DTB file: 838 * 1. Load configured DTB file in grub.cfg. 839 * 2. Load DTB file in UEFI Fv. 840 */ 841 /* Load DTB file in UEFI Fv. */ 842 Status = HiKeyInstallFdt (); 843 if (EFI_ERROR (Status)) { 844 DEBUG ((EFI_D_ERROR, "%a: failed to install Fdt file\n", __func__)); 845 return; 846 } 847 } 848 849 EFI_STATUS 850 HiKeyBootMenuInstall ( 851 IN VOID 852 ) 853 { 854 EFI_STATUS Status; 855 EFI_EVENT EndOfDxeEvent; 856 857 Status = gBS->CreateEventEx ( 858 EVT_NOTIFY_SIGNAL, 859 TPL_CALLBACK, 860 HiKeyOnEndOfDxe, 861 &mIsEndOfDxeEvent, 862 &gEfiEndOfDxeEventGroupGuid, 863 &EndOfDxeEvent 864 ); 865 ASSERT_EFI_ERROR (Status); 866 return Status; 867 } 868 869