Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
249 changes: 249 additions & 0 deletions kernelflinger.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down