diff --git a/kernelflinger.c b/kernelflinger.c index 7d8cce50..3c1e7a21 100644 --- a/kernelflinger.c +++ b/kernelflinger.c @@ -123,6 +123,8 @@ static const CHAR16 __attribute__((used)) magic[] = L"### kernelflinger ###"; * reset to zero. */ #define WATCHDOG_DELAY (10 * 60) +#define MAX_CMD_BUF 0x1000 +static CHAR8 cmd_buf[MAX_CMD_BUF]; static EFI_HANDLE g_disk_device; static EFI_LOADED_IMAGE *g_loaded_image; @@ -433,6 +435,7 @@ static enum boot_target check_watchdog(VOID) return NORMAL_BOOT; } +#ifndef USE_SBL static enum boot_target check_command_line(VOID) { UINTN argc, pos; @@ -492,6 +495,252 @@ static enum boot_target check_command_line(VOID) return bt; } +#else +/* + * Boot mode field definitions. + */ +static union bootMode +{ + UINT16 _bits; + struct { + UINT16 target : 5; /* [4:0] */ + UINT16 do_mrc_training : 1; /* [5] */ + UINT16 do_save_mrc_data : 1; /* [6] */ + UINT16 do_flash_update : 1; /* [7] */ + UINT16 silent : 1; /* [8] */ + UINT16 _reserved : 1; /* [9] */ + UINT16 action : 2; /* [11:10] 0:boot,1:CLI,2:halt,3:reset */ + UINT16 dipsw : 4; /* [15:12] */ + }; +} bootMode; + +static enum boot_target check_command_line() +{ + EFI_STATUS ret; + enum boot_target target = NORMAL_BOOT; + static EFI_LOADED_IMAGE *limg; + UINTN argc, i, j; + CHAR16 **argv; + CHAR16 *options; + UINTN cmd_len = 0; + CHAR8 arg8[256] = ""; + UINTN arglen; + + enum CmdType + { + RESET, + BOOT_TARGET, + BOOT, + SECUREBOOT, + BOOTVERSION, + SERIALNO, + FIRMWARE_BOOTTIME, + BOOTREASON, + FIRMWARE_STATUS, + }; + + struct Cmdline + { + CHAR8 *name; + UINTN length; + enum CmdType type; + }; + + struct Cmdline CmdlineArray[] = { + { + (CHAR8 *)"reset=", + strlen((CHAR8 *)"reset="), + RESET + }, + { + (CHAR8 *)"boot_target=", + strlen((CHAR8 *)"boot_target="), + BOOT_TARGET + }, + { + (CHAR8 *)"fw.boot=", + strlen((CHAR8 *)"fw.boot="), + BOOT + }, + { + (CHAR8 *)"SecureBoot=", + strlen((CHAR8 *)"SecureBoot="), + SECUREBOOT + }, + { + (CHAR8 *)"androidboot.bootloader=", + strlen((CHAR8 *)"androidboot.bootloader="), + BOOTVERSION + }, + { + (CHAR8 *)"androidboot.bootreason=", + strlen((CHAR8 *)"androidboot.bootreason="), + BOOTREASON + }, + { + (CHAR8 *)"androidboot.serialno=", + strlen((CHAR8 *)"androidboot.serialno="), + SERIALNO + }, + { + (CHAR8 *)"fw_boottsc=", + strlen("fw_boottsc="), + FIRMWARE_BOOTTIME + }, + { + (CHAR8 *)"fw.status=", + strlen((CHAR8 *)"fw.status="), + FIRMWARE_STATUS + }, + }; + + CHAR8 *nptr = NULL; + ret = uefi_call_wrapper(BS->OpenProtocol, 6, g_parent_image, + &LoadedImageProtocol, (VOID **)&limg, + g_parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(ret)) { + efi_perror(ret, L"Failed to open LoadedImageProtocol"); + return FASTBOOT; + } + + ret = get_argv(limg, &argc, &argv, &options); + if (EFI_ERROR(ret)) + return FASTBOOT; + + cmd_buf[0] = 0; + + for (i = 0; i < argc; i++) { + debug(L" cmd %02d: %s", i, argv[i]); + arglen = StrLen(argv[i]); + + if (arglen > (int)sizeof(arg8) - 2) + arglen = sizeof(arg8) - 2; + debug(L" cmd %02d length: %d", i, arglen); + + ret = str_to_stra((CHAR8 *)arg8, argv[i], arglen + 1); + if (EFI_ERROR(ret)) { + efi_perror(ret, L"Non-ascii characters in command line"); + return FASTBOOT; + } + + if (cmd_len + arglen + 1 < MAX_CMD_BUF) { + for (j = 0; j < sizeof(CmdlineArray)/sizeof(CmdlineArray[0]); j++) { + if((arglen >= CmdlineArray[j].length) && !strncmp(arg8, CmdlineArray[j].name, CmdlineArray[j].length)) + break; + } + + if (j < sizeof(CmdlineArray)/sizeof(CmdlineArray[0])) { + switch(CmdlineArray[j].type) { + /* Parse "reset=xxx" */ + case RESET: + set_reboot_reason(argv[i] + CmdlineArray[j].length); + continue; + + /* Parse "fw.boot_target=xxxx" */ + case BOOT_TARGET: + nptr = (CHAR8 *)(arg8 + CmdlineArray[j].length); + /* Only handle CRASHMODE case, other mode should be decided by "fw.boot". */ + if (!strcmp(nptr, (CHAR8 *)"CRASHMODE")) { + target = CRASHMODE; + goto out; + } + continue; + + /* Parse "fw.boot=xx" */ + case BOOT: + nptr = (CHAR8 *)(arg8 + CmdlineArray[j].length); + bootMode._bits = (UINT16)strtoul((char *)nptr, 0, 16); + target = bootMode.target; + break; + + /* Parse "SecureBoot=x" */ + case SECUREBOOT: { + UINT8 val; + nptr = (CHAR8 *)(arg8 + CmdlineArray[j].length); + val = (UINT8)strtoul((char *)nptr, 0, 10); + ret = set_platform_secure_boot(val); + if (EFI_ERROR(ret)) + efi_perror(ret, L"Failed to set secure boot"); + break; + } + + /* Parse "fw.status=x" */ + case FIRMWARE_STATUS: { + union + { + struct + { + UINT32 secure_boot:1; + UINT32 measured_boot:1; + UINT32 dci_debug_npk:1; + UINT32 eom:1; + }bit; + UINT32 val; + } sbl_status; + + nptr = (CHAR8 *)(arg8 + CmdlineArray[j].length); + sbl_status.val = (UINT32)strtoul((char *)nptr, 0, 16); + ret = set_platform_secure_boot(sbl_status.bit.secure_boot); + if (EFI_ERROR(ret)) + efi_perror(ret, L"Failed to set secure boot"); + break; + } + + /* Parse "fw_boottsc=xxxxx" */ + case FIRMWARE_BOOTTIME: { + UINT64 VALUE; + UINT32 cpu_khz; + nptr = (CHAR8 *)(arg8 + CmdlineArray[j].length); + VALUE = (UINT64)strtoull((char *)nptr, 0, 10); + cpu_khz = get_cpu_freq() * 1000; + //EFI_ENTER_POINT boot time is recorded in ms + set_efi_enter_point(VALUE /cpu_khz); + continue; + } + + /* Parse "android.bootloader=xxxxx" */ + case BOOTVERSION: + continue; + + /* Parse "android.serialno=xxxxx " */ + case SERIALNO: + continue; + + /* Parse "androidboot.bootreason=xxxxx " */ + case BOOTREASON: + continue; + + default: + continue; + } + } + + if (cmd_buf[0] != 0) { + ret = strncpy_s((CHAR8 *)(cmd_buf + cmd_len), MAX_CMD_BUF - cmd_len, (const CHAR8 *)" ", 1); + if (EFI_ERROR(ret)) { + target = FASTBOOT; + goto out; + } + cmd_len++; + } + + ret = strncpy_s((CHAR8 *)(cmd_buf + cmd_len), MAX_CMD_BUF - cmd_len, (const CHAR8 *)arg8, arglen); + if (EFI_ERROR(ret)) { + target = FASTBOOT; + goto out; + } + cmd_len += arglen; + } + } + +out: + debug(L"boot target: %d", target); + FreePool(argv); + FreePool(options); + return target; +} +#endif + static enum boot_target check_battery_inserted(void) { enum wake_sources wake_source;