mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-24 02:05:01 +00:00
Dev-mode only boots official kernels by default
Although we're now using a single unified BIOS, it is pretty nice to be able to get a shell in developer mode while still using verified boot for the kernel and filesystem. Alex & ZGB implemented this by requiring the dev-mode user to install a special dev-mode BIOS. We don't do that, but we DO require setting a special flag with "crossystem" to accomplish the same thing. In order to allow booting a self-signed kernel, you must boot in developer mode, open a shell, and run this: crossystem dev_boot_custom=1 Special note to internal developers: If you're in the habit (as I am) of booting directly from a USB stick in dev-mode, you'll have to run this: crossystem dev_boot_custom=1 dev_boot_usb=1 Just using dev_boot_usb=1 is no longer enough, because the USB kernel is signed using the recovery key and by pressing Ctrl-U, we validate it with the kernel data key. That worked before this change because any self-signed kernel was fine, and that's how the USB key was treated. Now it actually requires a verified signature until you enable dev_boot_custom=1 also. BUG=chrome-os-partner:5954 TEST=manual Boot once in normal mode, which clears the special flags. Then switch to developer mode. You should be able to boot and get a root shell. Run crossystem dev_boot_usb=1 Obtain a USB recovery image that's keyed differently. For example, if you're testing with dev-keys, use a PVT-signed image or vice-versa. Reboot into dev-mode with the USB recovery stick inserted. At the dev-mode screen, press Ctrl-U. You should hear a single beep, but it should not boot. Press Ctrl-D to boot from the hard drive, log in to a shell and run crossystem dev_boot_custom=1 Repeat the previous test. This time when you press Ctrl-U, it should boot the recovery image. Turn the system off before it does anything. That's it. Change-Id: I1811ee9a188974b3f94c83c52b00b60028b86c69 Reviewed-on: https://gerrit.chromium.org/gerrit/11442 Tested-by: Bill Richardson <wfrichar@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
@@ -54,6 +54,8 @@ typedef enum VbNvParam {
|
|||||||
VBNV_TEST_ERROR_NUM,
|
VBNV_TEST_ERROR_NUM,
|
||||||
/* Allow booting from USB in developer mode. 0=no, 1=yes. */
|
/* Allow booting from USB in developer mode. 0=no, 1=yes. */
|
||||||
VBNV_DEV_BOOT_USB,
|
VBNV_DEV_BOOT_USB,
|
||||||
|
/* Allow booting self-signed images in developer mode. 0=no, 1=yes. */
|
||||||
|
VBNV_DEV_BOOT_CUSTOM,
|
||||||
} VbNvParam;
|
} VbNvParam;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -234,6 +234,7 @@ typedef struct VbKernelPreambleHeader {
|
|||||||
#define VBSD_LKP_CHECK_PREAMBLE_VALID 11
|
#define VBSD_LKP_CHECK_PREAMBLE_VALID 11
|
||||||
#define VBSD_LKP_CHECK_BODY_ADDRESS 12
|
#define VBSD_LKP_CHECK_BODY_ADDRESS 12
|
||||||
#define VBSD_LKP_CHECK_BODY_OFFSET 13
|
#define VBSD_LKP_CHECK_BODY_OFFSET 13
|
||||||
|
#define VBSD_LKP_CHECK_SELF_SIGNED 14
|
||||||
#define VBSD_LKP_CHECK_BODY_EXCEEDS_MEM 15
|
#define VBSD_LKP_CHECK_BODY_EXCEEDS_MEM 15
|
||||||
#define VBSD_LKP_CHECK_BODY_EXCEEDS_PART 16
|
#define VBSD_LKP_CHECK_BODY_EXCEEDS_PART 16
|
||||||
#define VBSD_LKP_CHECK_READ_DATA 17
|
#define VBSD_LKP_CHECK_READ_DATA 17
|
||||||
|
|||||||
@@ -97,10 +97,11 @@ uint32_t VbTryLoadKernel(VbCommonParams* cparams, LoadKernelParams* p,
|
|||||||
/* Handle a normal boot. */
|
/* Handle a normal boot. */
|
||||||
VbError_t VbBootNormal(VbCommonParams* cparams, LoadKernelParams* p) {
|
VbError_t VbBootNormal(VbCommonParams* cparams, LoadKernelParams* p) {
|
||||||
|
|
||||||
/* Force dev_boot_usb flag disabled. This ensures the flag will be
|
/* Force dev_boot_* flags disabled. This ensures they will be
|
||||||
* initially disabled if the user later transitions back into
|
* initially disabled if the user later transitions back into
|
||||||
* developer mode. */
|
* developer mode. */
|
||||||
VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 0);
|
VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 0);
|
||||||
|
VbNvSet(&vnc, VBNV_DEV_BOOT_CUSTOM, 0);
|
||||||
|
|
||||||
/* Boot from fixed disk only */
|
/* Boot from fixed disk only */
|
||||||
return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED);
|
return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED);
|
||||||
|
|||||||
@@ -521,6 +521,11 @@ VbError_t VbDisplayDebugInfo(VbCommonParams* cparams, VbNvContext *vncptr) {
|
|||||||
used += Strncat(buf + used, "\ndev_boot_usb: ", DEBUG_INFO_SIZE - used);
|
used += Strncat(buf + used, "\ndev_boot_usb: ", DEBUG_INFO_SIZE - used);
|
||||||
used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, i, 10, 0);
|
used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, i, 10, 0);
|
||||||
|
|
||||||
|
/* Add dev_boot_custom flag */
|
||||||
|
VbNvGet(vncptr, VBNV_DEV_BOOT_CUSTOM, &i);
|
||||||
|
used += Strncat(buf + used, "\ndev_boot_custom: ", DEBUG_INFO_SIZE - used);
|
||||||
|
used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, i, 10, 0);
|
||||||
|
|
||||||
/* Add TPM versions */
|
/* Add TPM versions */
|
||||||
used += Strncat(buf + used, "\nTPM: fwver=0x", DEBUG_INFO_SIZE - used);
|
used += Strncat(buf + used, "\nTPM: fwver=0x", DEBUG_INFO_SIZE - used);
|
||||||
used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used,
|
used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used,
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData* gptdata) {
|
|||||||
/* disable MSVC warning on const logical expression (as in } while(0);) */
|
/* disable MSVC warning on const logical expression (as in } while(0);) */
|
||||||
__pragma(warning(disable: 4127))
|
__pragma(warning(disable: 4127))
|
||||||
|
|
||||||
|
|
||||||
VbError_t LoadKernel(LoadKernelParams* params) {
|
VbError_t LoadKernel(LoadKernelParams* params) {
|
||||||
VbSharedDataHeader* shared = (VbSharedDataHeader*)params->shared_data_blob;
|
VbSharedDataHeader* shared = (VbSharedDataHeader*)params->shared_data_blob;
|
||||||
VbSharedDataKernelCall* shcall = NULL;
|
VbSharedDataKernelCall* shcall = NULL;
|
||||||
@@ -139,6 +140,7 @@ VbError_t LoadKernel(LoadKernelParams* params) {
|
|||||||
int rec_switch, dev_switch;
|
int rec_switch, dev_switch;
|
||||||
BootMode boot_mode;
|
BootMode boot_mode;
|
||||||
uint32_t test_err = 0;
|
uint32_t test_err = 0;
|
||||||
|
uint32_t allow_self_signed = 0;
|
||||||
|
|
||||||
VbError_t retval = VBERROR_UNKNOWN;
|
VbError_t retval = VBERROR_UNKNOWN;
|
||||||
int recovery = VBNV_RECOVERY_RO_UNSPECIFIED;
|
int recovery = VBNV_RECOVERY_RO_UNSPECIFIED;
|
||||||
@@ -162,12 +164,14 @@ VbError_t LoadKernel(LoadKernelParams* params) {
|
|||||||
/* Calculate switch positions and boot mode */
|
/* Calculate switch positions and boot mode */
|
||||||
rec_switch = (BOOT_FLAG_RECOVERY & params->boot_flags ? 1 : 0);
|
rec_switch = (BOOT_FLAG_RECOVERY & params->boot_flags ? 1 : 0);
|
||||||
dev_switch = (BOOT_FLAG_DEVELOPER & params->boot_flags ? 1 : 0);
|
dev_switch = (BOOT_FLAG_DEVELOPER & params->boot_flags ? 1 : 0);
|
||||||
if (rec_switch)
|
if (rec_switch) {
|
||||||
boot_mode = kBootRecovery;
|
boot_mode = kBootRecovery;
|
||||||
else if (dev_switch)
|
} else if (dev_switch) {
|
||||||
boot_mode = kBootDev;
|
boot_mode = kBootDev;
|
||||||
else
|
VbNvGet(vnc, VBNV_DEV_BOOT_CUSTOM, &allow_self_signed);
|
||||||
|
} else {
|
||||||
boot_mode = kBootNormal;
|
boot_mode = kBootNormal;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set up tracking for this call. This wraps around if called many times,
|
/* Set up tracking for this call. This wraps around if called many times,
|
||||||
* so we need to initialize the call entry each time. */
|
* so we need to initialize the call entry each time. */
|
||||||
@@ -250,7 +254,7 @@ VbError_t LoadKernel(LoadKernelParams* params) {
|
|||||||
int key_block_valid = 1;
|
int key_block_valid = 1;
|
||||||
|
|
||||||
VBDEBUG(("Found kernel entry at %" PRIu64 " size %" PRIu64 "\n",
|
VBDEBUG(("Found kernel entry at %" PRIu64 " size %" PRIu64 "\n",
|
||||||
part_start, part_size));
|
part_start, part_size));
|
||||||
|
|
||||||
/* Set up tracking for this partition. This wraps around if called
|
/* Set up tracking for this partition. This wraps around if called
|
||||||
* many times, so initialize the partition entry each time. */
|
* many times, so initialize the partition entry each time. */
|
||||||
@@ -293,8 +297,14 @@ VbError_t LoadKernel(LoadKernelParams* params) {
|
|||||||
if (kBootDev != boot_mode)
|
if (kBootDev != boot_mode)
|
||||||
goto bad_kernel;
|
goto bad_kernel;
|
||||||
|
|
||||||
/* In developer mode, we can continue if the SHA-512 hash of the key
|
/* In developer mode, we have to explictly allow self-signed kernels */
|
||||||
* block is valid. */
|
if (!allow_self_signed) {
|
||||||
|
VBDEBUG(("Self-signed custom kernels are not enabled.\n"));
|
||||||
|
shpart->check_result = VBSD_LKP_CHECK_SELF_SIGNED;
|
||||||
|
goto bad_kernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allow the kernel if the SHA-512 hash of the key block is valid. */
|
||||||
if (0 != KeyBlockVerify(key_block, KBUF_SIZE, kernel_subkey, 1)) {
|
if (0 != KeyBlockVerify(key_block, KBUF_SIZE, kernel_subkey, 1)) {
|
||||||
VBDEBUG(("Verifying key block hash failed.\n"));
|
VBDEBUG(("Verifying key block hash failed.\n"));
|
||||||
shpart->check_result = VBSD_LKP_CHECK_KEY_BLOCK_HASH;
|
shpart->check_result = VBSD_LKP_CHECK_KEY_BLOCK_HASH;
|
||||||
@@ -489,7 +499,7 @@ VbError_t LoadKernel(LoadKernelParams* params) {
|
|||||||
/* Continue, so that we skip the error handling code below */
|
/* Continue, so that we skip the error handling code below */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bad_kernel:
|
bad_kernel:
|
||||||
/* Handle errors parsing this kernel */
|
/* Handle errors parsing this kernel */
|
||||||
if (NULL != data_key)
|
if (NULL != data_key)
|
||||||
RSAPublicKeyFree(data_key);
|
RSAPublicKeyFree(data_key);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#define DEV_FLAGS_OFFSET 4
|
#define DEV_FLAGS_OFFSET 4
|
||||||
#define DEV_BOOT_USB_MASK 0x01
|
#define DEV_BOOT_USB_MASK 0x01
|
||||||
|
#define DEV_BOOT_CUSTOM_MASK 0x02
|
||||||
|
|
||||||
#define FIRMWARE_FLAGS_OFFSET 5
|
#define FIRMWARE_FLAGS_OFFSET 5
|
||||||
#define FIRMWARE_TEST_ERR_FUNC_MASK 0x38
|
#define FIRMWARE_TEST_ERR_FUNC_MASK 0x38
|
||||||
@@ -142,6 +143,10 @@ int VbNvGet(VbNvContext* context, VbNvParam param, uint32_t* dest) {
|
|||||||
*dest = (raw[DEV_FLAGS_OFFSET] & DEV_BOOT_USB_MASK ? 1 : 0);
|
*dest = (raw[DEV_FLAGS_OFFSET] & DEV_BOOT_USB_MASK ? 1 : 0);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case VBNV_DEV_BOOT_CUSTOM:
|
||||||
|
*dest = (raw[DEV_FLAGS_OFFSET] & DEV_BOOT_CUSTOM_MASK ? 1 : 0);
|
||||||
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -227,6 +232,13 @@ int VbNvSet(VbNvContext* context, VbNvParam param, uint32_t value) {
|
|||||||
raw[DEV_FLAGS_OFFSET] &= ~DEV_BOOT_USB_MASK;
|
raw[DEV_FLAGS_OFFSET] &= ~DEV_BOOT_USB_MASK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VBNV_DEV_BOOT_CUSTOM:
|
||||||
|
if (value)
|
||||||
|
raw[DEV_FLAGS_OFFSET] |= DEV_BOOT_CUSTOM_MASK;
|
||||||
|
else
|
||||||
|
raw[DEV_FLAGS_OFFSET] &= ~DEV_BOOT_CUSTOM_MASK;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -390,6 +390,8 @@ int VbGetSystemPropertyInt(const char* name) {
|
|||||||
value = VbGetNvStorage(VBNV_LOCALIZATION_INDEX);
|
value = VbGetNvStorage(VBNV_LOCALIZATION_INDEX);
|
||||||
} else if (!strcasecmp(name,"dev_boot_usb")) {
|
} else if (!strcasecmp(name,"dev_boot_usb")) {
|
||||||
value = VbGetNvStorage(VBNV_DEV_BOOT_USB);
|
value = VbGetNvStorage(VBNV_DEV_BOOT_USB);
|
||||||
|
} else if (!strcasecmp(name,"dev_boot_custom")) {
|
||||||
|
value = VbGetNvStorage(VBNV_DEV_BOOT_CUSTOM);
|
||||||
}
|
}
|
||||||
/* Other parameters */
|
/* Other parameters */
|
||||||
else if (!strcasecmp(name,"cros_debug")) {
|
else if (!strcasecmp(name,"cros_debug")) {
|
||||||
@@ -469,6 +471,8 @@ int VbSetSystemPropertyInt(const char* name, int value) {
|
|||||||
return VbSetNvStorage(VBNV_LOCALIZATION_INDEX, value);
|
return VbSetNvStorage(VBNV_LOCALIZATION_INDEX, value);
|
||||||
} else if (!strcasecmp(name,"dev_boot_usb")) {
|
} else if (!strcasecmp(name,"dev_boot_usb")) {
|
||||||
return VbSetNvStorage(VBNV_DEV_BOOT_USB, value);
|
return VbSetNvStorage(VBNV_DEV_BOOT_USB, value);
|
||||||
|
} else if (!strcasecmp(name,"dev_boot_custom")) {
|
||||||
|
return VbSetNvStorage(VBNV_DEV_BOOT_CUSTOM, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ static VbNvField nvfields[] = {
|
|||||||
{VBNV_TEST_ERROR_FUNC, 0, 1, 7, "verified boot test error func"},
|
{VBNV_TEST_ERROR_FUNC, 0, 1, 7, "verified boot test error func"},
|
||||||
{VBNV_TEST_ERROR_NUM, 0, 3, 6, "verified boot test error number"},
|
{VBNV_TEST_ERROR_NUM, 0, 3, 6, "verified boot test error number"},
|
||||||
{VBNV_DEV_BOOT_USB, 0, 1, 0, "dev boot usb"},
|
{VBNV_DEV_BOOT_USB, 0, 1, 0, "dev boot usb"},
|
||||||
|
{VBNV_DEV_BOOT_CUSTOM, 0, 1, 0, "dev boot custom"},
|
||||||
{0, 0, 0, 0, NULL}
|
{0, 0, 0, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ const Param sys_param_list[] = {
|
|||||||
{"dbg_reset", CAN_WRITE, "Debug reset mode request (writable)"},
|
{"dbg_reset", CAN_WRITE, "Debug reset mode request (writable)"},
|
||||||
{"dev_boot_usb", CAN_WRITE,
|
{"dev_boot_usb", CAN_WRITE,
|
||||||
"Enable developer mode boot from USB/SD (writable)"},
|
"Enable developer mode boot from USB/SD (writable)"},
|
||||||
|
{"dev_boot_custom", CAN_WRITE,
|
||||||
|
"Enable developer mode boot using self-signed kernels (writable)"},
|
||||||
{"devsw_boot", 0, "Developer switch position at boot"},
|
{"devsw_boot", 0, "Developer switch position at boot"},
|
||||||
{"devsw_cur", 0, "Developer switch current position"},
|
{"devsw_cur", 0, "Developer switch current position"},
|
||||||
{"ecfw_act", IS_STRING, "Active EC firmware"},
|
{"ecfw_act", IS_STRING, "Active EC firmware"},
|
||||||
|
|||||||
Reference in New Issue
Block a user