summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2017-10-20 12:38:40 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-11-17 20:18:19 -0800
commit4aaaeca130a701a06cb898d9a17eddf67daa3617 (patch)
tree1f656152480b06b1c62589282249058d58702f88
parent6014de9844835472b821d8ca61909a0ed6930dfe (diff)
downloadvboot-4aaaeca130a701a06cb898d9a17eddf67daa3617.tar.gz
nvstorage: Add kernel max rollforward NV storage field
This just adds the kernel_max_rollforward field to the nvstorage libraries and crossystem. The firmware does not use it yet; that's coming in a subsequent CL. 16 of the fields's 32 bits are taken from unused bytes of the kernel field. This has no effect on existing usage. BUG=chromium:783997 BRANCH=none TEST=make runtests Also manual testing. In a root shell: crossystem kernel_max_rollforward --> Should default to 0 crossystem kernel_max_rollforward=0xfffffffe crossystem kernel_max_rollforward --> Should be 0xfffffffe (Note that setting it to 0xffffffff is indistinguishable from the -1 value that the crossystem library uses to indicate error, so 0xffffffff isn't actually usable as a max rollforward limit. But 0xfffffffe is, and if we ever get so close to the limit that we need to use 0xffffffff, something has already gone horribly wrong with our versioning strategy...) Change-Id: I008f412e6ed3c0b59beb9881268585af69d1ff2e Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/765572 Reviewed-by: Julius Werner <jwerner@chromium.org>
-rw-r--r--firmware/2lib/2nvstorage.c24
-rw-r--r--firmware/2lib/include/2nvstorage.h9
-rw-r--r--firmware/2lib/include/2nvstorage_fields.h8
-rw-r--r--firmware/include/vboot_nvstorage.h5
-rw-r--r--firmware/lib/vboot_nvstorage.c35
-rw-r--r--host/lib/crossystem.c12
-rw-r--r--tests/vb2_nvstorage_tests.c4
-rw-r--r--tests/vboot_nvstorage_test.c4
-rw-r--r--utility/crossystem.c4
9 files changed, 76 insertions, 29 deletions
diff --git a/firmware/2lib/2nvstorage.c b/firmware/2lib/2nvstorage.c
index b40bbe78..08363362 100644
--- a/firmware/2lib/2nvstorage.c
+++ b/firmware/2lib/2nvstorage.c
@@ -121,10 +121,7 @@ uint32_t vb2_nv_get(struct vb2_context *ctx, enum vb2_nv_param param)
return p[VB2_NV_OFFS_LOCALIZATION];
case VB2_NV_KERNEL_FIELD:
- return (p[VB2_NV_OFFS_KERNEL]
- | (p[VB2_NV_OFFS_KERNEL + 1] << 8)
- | (p[VB2_NV_OFFS_KERNEL + 2] << 16)
- | (p[VB2_NV_OFFS_KERNEL + 3] << 24));
+ return p[VB2_NV_OFFS_KERNEL1] | (p[VB2_NV_OFFS_KERNEL2] << 8);
case VB2_NV_DEV_BOOT_USB:
return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_USB);
@@ -175,6 +172,12 @@ uint32_t vb2_nv_get(struct vb2_context *ctx, enum vb2_nv_param param)
case VB2_NV_BATTERY_CUTOFF_REQUEST:
return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BATTERY_CUTOFF);
+
+ case VB2_NV_KERNEL_MAX_ROLLFORWARD:
+ return (p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD1]
+ | (p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD2] << 8)
+ | (p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD3] << 16)
+ | (p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD4] << 24));
}
/*
@@ -280,10 +283,8 @@ void vb2_nv_set(struct vb2_context *ctx,
break;
case VB2_NV_KERNEL_FIELD:
- p[VB2_NV_OFFS_KERNEL] = (uint8_t)(value);
- p[VB2_NV_OFFS_KERNEL + 1] = (uint8_t)(value >> 8);
- p[VB2_NV_OFFS_KERNEL + 2] = (uint8_t)(value >> 16);
- p[VB2_NV_OFFS_KERNEL + 3] = (uint8_t)(value >> 24);
+ p[VB2_NV_OFFS_KERNEL1] = (uint8_t)(value);
+ p[VB2_NV_OFFS_KERNEL2] = (uint8_t)(value >> 8);
break;
case VB2_NV_DEV_BOOT_USB:
@@ -356,6 +357,13 @@ void vb2_nv_set(struct vb2_context *ctx,
case VB2_NV_BATTERY_CUTOFF_REQUEST:
SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BATTERY_CUTOFF);
break;
+
+ case VB2_NV_KERNEL_MAX_ROLLFORWARD:
+ p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD1] = (uint8_t)(value);
+ p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD2] = (uint8_t)(value >> 8);
+ p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD3] = (uint8_t)(value >> 16);
+ p[VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD4] = (uint8_t)(value >> 24);
+ break;
}
/*
diff --git a/firmware/2lib/include/2nvstorage.h b/firmware/2lib/include/2nvstorage.h
index 66a5fdf1..e3226a58 100644
--- a/firmware/2lib/include/2nvstorage.h
+++ b/firmware/2lib/include/2nvstorage.h
@@ -42,7 +42,7 @@ enum vb2_nv_param {
* 8-bit value.
*/
VB2_NV_LOCALIZATION_INDEX,
- /* Field reserved for kernel/user-mode use; 32-bit value. */
+ /* Field reserved for kernel/user-mode use; 16-bit value. */
VB2_NV_KERNEL_FIELD,
/* Allow booting from USB in developer mode. 0=no, 1=yes. */
VB2_NV_DEV_BOOT_USB,
@@ -94,10 +94,15 @@ enum vb2_nv_param {
VB2_NV_FASTBOOT_UNLOCK_IN_FW,
/* Boot system when AC detected (0=no, 1=yes). */
VB2_NV_BOOT_ON_AC_DETECT,
- /* Try to update the EC-RO image after updating the EC-RW image(0=no, 1=yes). */
+ /*
+ * Try to update the EC-RO image after updating the EC-RW image
+ * (0=no, 1=yes).
+ */
VB2_NV_TRY_RO_SYNC,
/* Cut off battery and shutdown on next boot. */
VB2_NV_BATTERY_CUTOFF_REQUEST,
+ /* Maximum kernel version to roll forward to */
+ VB2_NV_KERNEL_MAX_ROLLFORWARD,
};
/* Set default boot in developer mode */
diff --git a/firmware/2lib/include/2nvstorage_fields.h b/firmware/2lib/include/2nvstorage_fields.h
index 018bdeb7..0ed3325a 100644
--- a/firmware/2lib/include/2nvstorage_fields.h
+++ b/firmware/2lib/include/2nvstorage_fields.h
@@ -29,8 +29,12 @@ enum vb2_nv_offset {
VB2_NV_OFFS_RECOVERY_SUBCODE = 6,
VB2_NV_OFFS_BOOT2 = 7,
VB2_NV_OFFS_MISC = 8,
- /* Offsets 9-10 are currently unused */
- VB2_NV_OFFS_KERNEL = 11, /* 11-14; field is 32 bits */
+ VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD1 = 9, /* bits 0-7 of 32 */
+ VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD2 = 10, /* bits 8-15 of 32 */
+ VB2_NV_OFFS_KERNEL1 = 11, /* bits 0-7 of 16 */
+ VB2_NV_OFFS_KERNEL2 = 12, /* bits 8-15 of 16 */
+ VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD3 = 13, /* bits 16-23 of 32 */
+ VB2_NV_OFFS_KERNEL_MAX_ROLLFORWARD4 = 14, /* bits 24-31 of 32 */
/* CRC must be last field */
VB2_NV_OFFS_CRC = 15
};
diff --git a/firmware/include/vboot_nvstorage.h b/firmware/include/vboot_nvstorage.h
index 8c7ff9d3..ecb5d007 100644
--- a/firmware/include/vboot_nvstorage.h
+++ b/firmware/include/vboot_nvstorage.h
@@ -122,8 +122,11 @@ typedef enum VbNvParam {
VBNV_TRY_RO_SYNC,
/*
* Finish mode transition (if requested), perform battery cut-off and
- * shutdown in next boot. */
+ * shutdown in next boot.
+ */
VBNV_BATTERY_CUTOFF_REQUEST,
+ /* Maximum kernel version to roll forward to */
+ VBNV_KERNEL_MAX_ROLLFORWARD,
} VbNvParam;
/* Set default boot in developer mode */
diff --git a/firmware/lib/vboot_nvstorage.c b/firmware/lib/vboot_nvstorage.c
index 3d6a65d7..9dc9dc3d 100644
--- a/firmware/lib/vboot_nvstorage.c
+++ b/firmware/lib/vboot_nvstorage.c
@@ -66,7 +66,14 @@
#define MISC_TRY_RO_SYNC 0x04
#define MISC_BATTERY_CUTOFF_REQUEST 0x08
-#define KERNEL_FIELD_OFFSET 11
+#define KERNEL_MAX_ROLLFORWARD1_OFFSET 9 /* Low bits */
+#define KERNEL_MAX_ROLLFORWARD2_OFFSET 10
+#define KERNEL_MAX_ROLLFORWARD3_OFFSET 13
+#define KERNEL_MAX_ROLLFORWARD4_OFFSET 14 /* High bits */
+
+#define KERNEL_FIELD1_OFFSET 11 /* Low bits */
+#define KERNEL_FIELD2_OFFSET 12 /* Low bits */
+
#define CRC_OFFSET 15
int VbNvSetup(VbNvContext *context)
@@ -141,10 +148,8 @@ int VbNvGet(VbNvContext *context, VbNvParam param, uint32_t *dest)
return 0;
case VBNV_KERNEL_FIELD:
- *dest = (raw[KERNEL_FIELD_OFFSET]
- | (raw[KERNEL_FIELD_OFFSET + 1] << 8)
- | (raw[KERNEL_FIELD_OFFSET + 2] << 16)
- | (raw[KERNEL_FIELD_OFFSET + 3] << 24));
+ *dest = (raw[KERNEL_FIELD1_OFFSET]
+ | (raw[KERNEL_FIELD2_OFFSET] << 8));
return 0;
case VBNV_DEV_BOOT_USB:
@@ -237,6 +242,13 @@ int VbNvGet(VbNvContext *context, VbNvParam param, uint32_t *dest)
? 1 : 0;
return 0;
+ case VBNV_KERNEL_MAX_ROLLFORWARD:
+ *dest = (raw[KERNEL_MAX_ROLLFORWARD1_OFFSET]
+ | (raw[KERNEL_MAX_ROLLFORWARD2_OFFSET] << 8)
+ | (raw[KERNEL_MAX_ROLLFORWARD3_OFFSET] << 16)
+ | (raw[KERNEL_MAX_ROLLFORWARD4_OFFSET] << 24));
+ return 0;
+
default:
return 1;
}
@@ -306,10 +318,8 @@ int VbNvSet(VbNvContext *context, VbNvParam param, uint32_t value)
break;
case VBNV_KERNEL_FIELD:
- raw[KERNEL_FIELD_OFFSET] = (uint8_t)(value);
- raw[KERNEL_FIELD_OFFSET + 1] = (uint8_t)(value >> 8);
- raw[KERNEL_FIELD_OFFSET + 2] = (uint8_t)(value >> 16);
- raw[KERNEL_FIELD_OFFSET + 3] = (uint8_t)(value >> 24);
+ raw[KERNEL_FIELD1_OFFSET] = (uint8_t)(value);
+ raw[KERNEL_FIELD2_OFFSET] = (uint8_t)(value >> 8);
break;
case VBNV_DEV_BOOT_USB:
@@ -469,6 +479,13 @@ int VbNvSet(VbNvContext *context, VbNvParam param, uint32_t value)
raw[MISC_OFFSET] &= ~MISC_BATTERY_CUTOFF_REQUEST;
break;
+ case VBNV_KERNEL_MAX_ROLLFORWARD:
+ raw[KERNEL_MAX_ROLLFORWARD1_OFFSET] = (uint8_t)(value);
+ raw[KERNEL_MAX_ROLLFORWARD2_OFFSET] = (uint8_t)(value >> 8);
+ raw[KERNEL_MAX_ROLLFORWARD3_OFFSET] = (uint8_t)(value >> 16);
+ raw[KERNEL_MAX_ROLLFORWARD4_OFFSET] = (uint8_t)(value >> 24);
+ break;
+
default:
return 1;
}
diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c
index 16ba2116..216ff32c 100644
--- a/host/lib/crossystem.c
+++ b/host/lib/crossystem.c
@@ -72,14 +72,14 @@ static const char *fw_results[] = {"unknown", "trying", "success", "failure"};
static const char *default_boot[] = {"disk", "usb", "legacy"};
/* Masks for kern_nv usage by kernel. */
-#define KERN_NV_FWUPDATE_TRIES_MASK 0x0000000F
-#define KERN_NV_BLOCK_DEVMODE_FLAG 0x00000010
-#define KERN_NV_TPM_ATTACK_FLAG 0x00000020
+#define KERN_NV_FWUPDATE_TRIES_MASK 0x000F
+#define KERN_NV_BLOCK_DEVMODE_FLAG 0x0010
+#define KERN_NV_TPM_ATTACK_FLAG 0x0020
/* If you want to use the remaining currently-unused bits in kern_nv
* for something kernel-y, define a new field (the way we did for
* fwupdate_tries). Don't just modify kern_nv directly, because that
* makes it too easy to accidentally corrupt other sub-fields. */
-#define KERN_NV_CURRENTLY_UNUSED 0xFFFFFFC0
+#define KERN_NV_CURRENTLY_UNUSED 0xFFC0
/* Return true if the FWID starts with the specified string. */
int FwidStartsWith(const char *start)
@@ -523,6 +523,8 @@ int VbGetSystemPropertyInt(const char *name)
value = VbGetNvStorage(VBNV_RECOVERY_SUBCODE);
} else if (!strcasecmp(name,"wipeout_request")) {
value = VbGetNvStorage(VBNV_FW_REQ_WIPEOUT);
+ } else if (!strcasecmp(name,"kernel_max_rollforward")) {
+ value = VbGetNvStorage(VBNV_KERNEL_MAX_ROLLFORWARD);
}
/* Other parameters */
else if (!strcasecmp(name,"cros_debug")) {
@@ -716,6 +718,8 @@ int VbSetSystemPropertyInt(const char *name, int value)
return VbSetNvStorage_WithBackup(VBNV_TRY_RO_SYNC, value);
} else if (!strcasecmp(name, "battery_cutoff_request")) {
return VbSetNvStorage(VBNV_BATTERY_CUTOFF_REQUEST, value);
+ } else if (!strcasecmp(name,"kernel_max_rollforward")) {
+ return VbSetNvStorage(VBNV_KERNEL_MAX_ROLLFORWARD, value);
}
return -1;
diff --git a/tests/vb2_nvstorage_tests.c b/tests/vb2_nvstorage_tests.c
index 2056f101..fe31a5ee 100644
--- a/tests/vb2_nvstorage_tests.c
+++ b/tests/vb2_nvstorage_tests.c
@@ -41,7 +41,7 @@ static struct nv_field nvfields[] = {
{VB2_NV_RECOVERY_REQUEST, 0, 0x42, 0xED, "recovery request"},
{VB2_NV_RECOVERY_SUBCODE, 0, 0x56, 0xAC, "recovery subcode"},
{VB2_NV_LOCALIZATION_INDEX, 0, 0x69, 0xB0, "localization index"},
- {VB2_NV_KERNEL_FIELD, 0, 0x12345678, 0xFEDCBA98, "kernel field"},
+ {VB2_NV_KERNEL_FIELD, 0, 0x1234, 0xFEDC, "kernel field"},
{VB2_NV_DEV_BOOT_USB, 0, 1, 0, "dev boot usb"},
{VB2_NV_DEV_BOOT_LEGACY, 0, 1, 0, "dev boot legacy"},
{VB2_NV_DEV_BOOT_SIGNED_ONLY, 0, 1, 0, "dev boot custom"},
@@ -56,6 +56,8 @@ static struct nv_field nvfields[] = {
{VB2_NV_FASTBOOT_UNLOCK_IN_FW, 0, 1, 0, "fastboot unlock in fw"},
{VB2_NV_BOOT_ON_AC_DETECT, 0, 1, 0, "boot on ac detect"},
{VB2_NV_TRY_RO_SYNC, 0, 1, 0, "try read only software sync"},
+ {VB2_NV_KERNEL_MAX_ROLLFORWARD, 0, 0x12345678, 0xFEDCBA98,
+ "kernel max rollforward"},
{0, 0, 0, 0, NULL}
};
diff --git a/tests/vboot_nvstorage_test.c b/tests/vboot_nvstorage_test.c
index 687048e1..c461978f 100644
--- a/tests/vboot_nvstorage_test.c
+++ b/tests/vboot_nvstorage_test.c
@@ -29,7 +29,7 @@ static VbNvField nvfields[] = {
{VBNV_TRY_B_COUNT, 0, 6, 15, "try B count"},
{VBNV_RECOVERY_REQUEST, 0, 0x42, 0xED, "recovery request"},
{VBNV_LOCALIZATION_INDEX, 0, 0x69, 0xB0, "localization index"},
- {VBNV_KERNEL_FIELD, 0, 0x12345678, 0xFEDCBA98, "kernel field"},
+ {VBNV_KERNEL_FIELD, 0, 0x1234, 0xFEDC, "kernel field"},
{VBNV_DEV_BOOT_USB, 0, 1, 0, "dev boot usb"},
{VBNV_DEV_BOOT_LEGACY, 0, 1, 0, "dev boot legacy"},
{VBNV_DEV_BOOT_SIGNED_ONLY, 0, 1, 0, "dev boot custom"},
@@ -49,6 +49,8 @@ static VbNvField nvfields[] = {
{VBNV_FASTBOOT_UNLOCK_IN_FW, 0, 1, 0, "fastboot unlock in firmware"},
{VBNV_BOOT_ON_AC_DETECT, 0, 1, 0, "boot on ac detect"},
{VBNV_TRY_RO_SYNC, 0, 1, 0, "try read only software sync"},
+ {VBNV_KERNEL_MAX_ROLLFORWARD, 0, 0x12345678, 0xFEDCBA98,
+ "kernel max rollforward"},
{0, 0, 0, 0, NULL}
};
diff --git a/utility/crossystem.c b/utility/crossystem.c
index 62e8a921..911d585d 100644
--- a/utility/crossystem.c
+++ b/utility/crossystem.c
@@ -70,7 +70,9 @@ const Param sys_param_list[] = {
{"fw_prev_result", IS_STRING, "Firmware result of previous boot (vboot2)"},
{"hwid", IS_STRING, "Hardware ID"},
{"inside_vm", 0, "Running in a VM?"},
- {"kern_nv", 0, "Non-volatile field for kernel use", "0x%08x"},
+ {"kern_nv", 0, "Non-volatile field for kernel use", "0x%04x"},
+ {"kernel_max_rollforward", CAN_WRITE, "Max kernel version to store into TPM",
+ "0x%08x"},
{"kernkey_vfy", IS_STRING, "Type of verification done on kernel key block"},
{"loc_idx", CAN_WRITE, "Localization index for firmware screens (writable)"},
{"mainfw_act", IS_STRING, "Active main firmware"},