diff options
-rw-r--r-- | libstb/Makefile.inc | 4 | ||||
-rw-r--r-- | libstb/drivers/Makefile.inc | 11 | ||||
-rw-r--r-- | libstb/drivers/romcode.c | 138 | ||||
-rw-r--r-- | libstb/drivers/romcode.h | 24 | ||||
-rw-r--r-- | libstb/rom.c | 2 | ||||
-rw-r--r-- | libstb/status_codes.h | 3 |
6 files changed, 181 insertions, 1 deletions
diff --git a/libstb/Makefile.inc b/libstb/Makefile.inc index 8b057de5..b4463cfd 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 00000000..63dead25 --- /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 00000000..94bd42c8 --- /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, ®_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 00000000..4152eaee --- /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 8ce64c2e..217ef132 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 __unused) 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 240cd954..0d7e5fb1 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 */ |