[Skiboot] [PATCH v2 11/31] libstb/drivers: add romcode driver

Claudio Carvalho cclaudio at linux.vnet.ibm.com
Wed Sep 28 18:01:10 AEST 2016


This adds a driver for the ROM verification code. The driver is compatible
with 'ibm,secureboot-v1'.

The presense of a verification code in the platform is indicated by the
presence of the ibm,secureboot node in the device tree.

The ibm,secureboot node is documented in 'doc/device-tree/ibm,secureboot.rst'

Signed-off-by: Claudio Carvalho <cclaudio at linux.vnet.ibm.com>
---
 libstb/Makefile.inc         |   4 +-
 libstb/drivers/Makefile.inc |  11 ++++
 libstb/drivers/romcode.c    | 138 ++++++++++++++++++++++++++++++++++++++++++++
 libstb/drivers/romcode.h    |  24 ++++++++
 libstb/rom.c                |   2 +
 libstb/status_codes.h       |   3 +
 6 files changed, 181 insertions(+), 1 deletion(-)
 create mode 100644 libstb/drivers/Makefile.inc
 create mode 100644 libstb/drivers/romcode.c
 create mode 100644 libstb/drivers/romcode.h

diff --git a/libstb/Makefile.inc b/libstb/Makefile.inc
index 8b057de..b4463cf 100644
--- a/libstb/Makefile.inc
+++ b/libstb/Makefile.inc
@@ -8,4 +8,6 @@ LIBSTB_SRCS = container.c rom.c tpm_chip.c
 LIBSTB_OBJS = $(LIBSTB_SRCS:%.c=%.o)
 LIBSTB = $(LIBSTB_DIR)/built-in.o
 
-$(LIBSTB): $(LIBSTB_OBJS:%=$(LIBSTB_DIR)/%)
+include $(SRC)/$(LIBSTB_DIR)/drivers/Makefile.inc
+
+$(LIBSTB): $(LIBSTB_OBJS:%=$(LIBSTB_DIR)/%) $(DRIVERS)
diff --git a/libstb/drivers/Makefile.inc b/libstb/drivers/Makefile.inc
new file mode 100644
index 0000000..63dead2
--- /dev/null
+++ b/libstb/drivers/Makefile.inc
@@ -0,0 +1,11 @@
+# -*-Makefile-*-
+
+DRIVERS_DIR = libstb/drivers
+
+SUBDIRS += $(DRIVERS_DIR)
+
+DRIVERS_SRCS = romcode.c
+DRIVERS_OBJS = $(DRIVERS_SRCS:%.c=%.o)
+DRIVERS = $(DRIVERS_DIR)/built-in.o
+
+$(DRIVERS): $(DRIVERS_OBJS:%=$(DRIVERS_DIR)/%)
diff --git a/libstb/drivers/romcode.c b/libstb/drivers/romcode.c
new file mode 100644
index 0000000..94bd42c
--- /dev/null
+++ b/libstb/drivers/romcode.c
@@ -0,0 +1,138 @@
+/* Copyright 2013-2016 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <chip.h>
+#include <xscom.h>
+#include <string.h>
+#include <skiboot.h>
+#include "../status_codes.h"
+#include "../rom.h"
+#include "romcode.h"
+
+#define DRIVER_NAME	"romcode"
+
+#define ROMCODE_MEMORY_SIZE	(16 * 1024)
+#define ROMCODE_XSCOM_ADDRESS	0x02020017
+
+/*
+ *  From the source code of the ROM code
+ */
+#define ROMCODE_SHA512_OFFSET		0x20
+#define ROMCODE_VERIFY_OFFSET		0x30
+
+static const char *compat = "ibm,secureboot-v1";
+static void *romcode_base_addr = NULL;
+static sha2_hash_t *hw_key_hash = NULL;
+
+/*
+ * Assembly interfaces to call into ROM code.
+ * func_ptr is the ROM code function address, followed
+ * by additional parameters as necessary
+ */
+ROM_response call_rom_verify(void *func_ptr, ROM_container_raw *container,
+			     ROM_hw_params *params);
+void call_rom_SHA512(void *func_ptr, const uint8_t *data, size_t len,
+		     uint8_t *digest);
+
+static int romcode_verify(void *container)
+{
+	ROM_hw_params hw_params;
+	ROM_response rc;
+
+	memset(&hw_params, 0, sizeof(ROM_hw_params));
+	memcpy(&hw_params.hw_key_hash, hw_key_hash, sizeof(sha2_hash_t));
+	rc = call_rom_verify(romcode_base_addr + ROMCODE_VERIFY_OFFSET,
+			     (ROM_container_raw*) container, &hw_params);
+	if (rc != ROM_DONE) {
+		/*
+		 * Verify failed. hw_params.log indicates what checking has
+		 * failed. This will abort the boot process.
+		 */
+		prlog(PR_ERR, "ROM: %s failed (rc=%d, hw_params.log=0x%llx)\n",
+		      __func__, rc, be64_to_cpu(hw_params.log));
+		return STB_VERIFY_FAILED;
+	}
+	return 0;
+}
+
+static void romcode_sha512(const uint8_t *data, size_t len, uint8_t *digest)
+{
+	memset(digest, 0, sizeof(sha2_hash_t));
+	call_rom_SHA512(romcode_base_addr + ROMCODE_SHA512_OFFSET,
+			data, len, digest);
+}
+
+static void romcode_cleanup(void) {
+	if (romcode_base_addr)
+		free(romcode_base_addr);
+	hw_key_hash = NULL;
+}
+
+static struct rom_driver_ops romcode_driver = {
+	.name    = DRIVER_NAME,
+	.verify  = romcode_verify,
+	.sha512  = romcode_sha512,
+	.cleanup = romcode_cleanup
+};
+
+void romcode_probe(const struct dt_node *node)
+{
+	/* This xscom register has the ROM code base address */
+	const uint32_t reg_addr = ROMCODE_XSCOM_ADDRESS;
+	uint64_t reg_data;
+	struct proc_chip *chip;
+	const char* hash_algo;
+
+	if (!dt_node_is_compatible(node, compat)) {
+		prlog(PR_DEBUG, "ROM: %s node is not compatible\n",
+		      node->name);
+		return;
+	}
+	/*
+	 * secureboot-v1 defines containers with sha512 hashes
+	 */
+	hash_algo = dt_prop_get(node, "hash-algo");
+	if (strcmp(hash_algo, "sha512")) {
+		/**
+		 * @fwts-label ROMHashAlgorithmInvalid
+		 * @fwts-advice Hostboot creates the ibm,secureboot node and
+		 * the hash-algo property. Check that the ibm,secureboot node
+		 * layout has not changed.
+		 */
+		prlog(PR_ERR, "ROM: hash-algo=%s not expected\n", hash_algo);
+		return;
+	}
+	hw_key_hash = (sha2_hash_t*) dt_prop_get(node, "hw-key-hash");
+	romcode_base_addr = malloc(ROMCODE_MEMORY_SIZE);
+	assert(romcode_base_addr);
+	/*
+	 * The logic that contains the ROM within the processor is implemented
+	 * in a way that it only responds to CI (cache inhibited) operations.
+	 * Due to performance issues we copy the verification code from the
+	 * secure ROM to RAM and we use memcpy_from_ci to do that.
+	 */
+	chip = next_chip(NULL);
+	xscom_read(chip->id, reg_addr, &reg_data);
+	memcpy_from_ci(romcode_base_addr, (void*) reg_data,
+		       ROMCODE_MEMORY_SIZE);
+	/*
+	 * Skiboot runs with IR (Instruction Relocation) &
+	 * DR (Data Relocation) off, so there is no need to either MMIO
+	 * the ROM code or set the memory region as executable.
+         * skiboot accesses the physical memory directly. Real mode.
+	 */
+	rom_set_driver(&romcode_driver);
+}
diff --git a/libstb/drivers/romcode.h b/libstb/drivers/romcode.h
new file mode 100644
index 0000000..4152eae
--- /dev/null
+++ b/libstb/drivers/romcode.h
@@ -0,0 +1,24 @@
+/* Copyright 2013-2016 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ROMCODE_H
+#define __ROMCODE_H
+
+#include <device.h>
+
+extern void romcode_probe(const struct dt_node *node);
+
+#endif /* __ROMCODE_H */
diff --git a/libstb/rom.c b/libstb/rom.c
index 9d2c6d7..81bafcc 100644
--- a/libstb/rom.c
+++ b/libstb/rom.c
@@ -16,6 +16,7 @@
 
 #include <skiboot.h>
 #include "rom.h"
+#include "drivers/romcode.h"
 
 static struct rom_driver_ops *rom_driver = NULL;
 
@@ -25,6 +26,7 @@ struct rom_driver_ops* rom_init(const struct dt_node *node)
 		goto end;
 
 	/* ROM drivers supported */
+	romcode_probe(node);
 
 	if (!rom_driver)
 		prlog(PR_NOTICE, "ROM: no rom driver found\n");
diff --git a/libstb/status_codes.h b/libstb/status_codes.h
index 240cd95..0d7e5fb 100644
--- a/libstb/status_codes.h
+++ b/libstb/status_codes.h
@@ -20,4 +20,7 @@
 /*  general return codes */
 #define STB_ERROR		-1
 
+/* secure boot */
+#define STB_VERIFY_FAILED  		-100
+
 #endif /* __STB_STATUS_CODES_H */
-- 
1.9.1



More information about the Skiboot mailing list