summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/sandbox/include/asm/io.h57
-rw-r--r--cmd/fdt.c2
-rw-r--r--common/spl/spl.c2
-rw-r--r--drivers/core/read.c3
-rw-r--r--include/dm/ofnode.h2
-rw-r--r--include/tpm.h15
-rw-r--r--lib/tpm.c60
7 files changed, 135 insertions, 6 deletions
diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
index ae6883f33d..59729f5635 100644
--- a/arch/sandbox/include/asm/io.h
+++ b/arch/sandbox/include/asm/io.h
@@ -47,6 +47,63 @@ phys_addr_t map_to_sysmem(const void *ptr);
#define writew(v, addr) ((void)addr)
#define writel(v, addr) ((void)addr)
+/*
+ * Clear and set bits in one shot. These macros can be used to clear and
+ * set multiple bits in a register using a single call. These macros can
+ * also be used to set a multiple-bit bit pattern using a mask, by
+ * specifying the mask in the 'clear' parameter and the new bit pattern
+ * in the 'set' parameter.
+ */
+
+#define out_arch(type,endian,a,v) write##type(cpu_to_##endian(v),a)
+#define in_arch(type,endian,a) endian##_to_cpu(read##type(a))
+
+#define out_le64(a,v) out_arch(q,le64,a,v)
+#define out_le32(a,v) out_arch(l,le32,a,v)
+#define out_le16(a,v) out_arch(w,le16,a,v)
+
+#define in_le64(a) in_arch(q,le64,a)
+#define in_le32(a) in_arch(l,le32,a)
+#define in_le16(a) in_arch(w,le16,a)
+
+#define out_be32(a,v) out_arch(l,be32,a,v)
+#define out_be16(a,v) out_arch(w,be16,a,v)
+
+#define in_be32(a) in_arch(l,be32,a)
+#define in_be16(a) in_arch(w,be16,a)
+
+#define out_8(a,v) writeb(v,a)
+#define in_8(a) readb(a)
+
+#define clrbits(type, addr, clear) \
+ out_##type((addr), in_##type(addr) & ~(clear))
+
+#define setbits(type, addr, set) \
+ out_##type((addr), in_##type(addr) | (set))
+
+#define clrsetbits(type, addr, clear, set) \
+ out_##type((addr), (in_##type(addr) & ~(clear)) | (set))
+
+#define clrbits_be32(addr, clear) clrbits(be32, addr, clear)
+#define setbits_be32(addr, set) setbits(be32, addr, set)
+#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set)
+
+#define clrbits_le32(addr, clear) clrbits(le32, addr, clear)
+#define setbits_le32(addr, set) setbits(le32, addr, set)
+#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set)
+
+#define clrbits_be16(addr, clear) clrbits(be16, addr, clear)
+#define setbits_be16(addr, set) setbits(be16, addr, set)
+#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set)
+
+#define clrbits_le16(addr, clear) clrbits(le16, addr, clear)
+#define setbits_le16(addr, set) setbits(le16, addr, set)
+#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set)
+
+#define clrbits_8(addr, clear) clrbits(8, addr, clear)
+#define setbits_8(addr, set) setbits(8, addr, set)
+#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
+
/* I/O access functions */
int inl(unsigned int addr);
int inw(unsigned int addr);
diff --git a/cmd/fdt.c b/cmd/fdt.c
index 955a0088c6..b783b0df42 100644
--- a/cmd/fdt.c
+++ b/cmd/fdt.c
@@ -256,7 +256,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
char *pathp; /* path */
char *prop; /* property */
int nodeoffset; /* node offset from libfdt */
- static char data[SCRATCHPAD]; /* storage for the property */
+ static char data[SCRATCHPAD] __aligned(4);/* property storage */
const void *ptmp;
int len; /* new length of the property */
int ret; /* return value */
diff --git a/common/spl/spl.c b/common/spl/spl.c
index aaddddd995..d232f67ba9 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -154,7 +154,7 @@ int spl_parse_image_header(struct spl_image_info *spl_image,
spl_image->os = image_get_os(header);
spl_image->name = image_get_name(header);
debug("spl: payload image: %.*s load addr: 0x%lx size: %d\n",
- (int)sizeof(spl_image->name), spl_image->name,
+ IH_NMLEN, spl_image->name,
spl_image->load_addr, spl_image->size);
#else
/* LEGACY image not supported */
diff --git a/drivers/core/read.c b/drivers/core/read.c
index eacf1716fd..5d440cee72 100644
--- a/drivers/core/read.c
+++ b/drivers/core/read.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <dm.h>
+#include <mapmem.h>
#include <dm/of_access.h>
int dev_read_u32_default(struct udevice *dev, const char *propname, int def)
@@ -61,7 +62,7 @@ void *dev_read_addr_ptr(struct udevice *dev)
{
fdt_addr_t addr = dev_read_addr(dev);
- return (addr == FDT_ADDR_T_NONE) ? NULL : (void *)addr;
+ return (addr == FDT_ADDR_T_NONE) ? NULL : map_sysmem(addr, 0);
}
fdt_addr_t dev_read_addr_size(struct udevice *dev, const char *property,
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 79374b8f91..8b9932a569 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -45,7 +45,7 @@ struct resource;
* the DT.
*
* @np: Pointer to device node, used for live tree
- * @flat_ptr: Pointer into flat device tree, used for flat tree. Note that this
+ * @of_offset: Pointer into flat device tree, used for flat tree. Note that this
* is not a really a pointer to a node: it is an offset value. See above.
*/
typedef union ofnode_union {
diff --git a/include/tpm.h b/include/tpm.h
index f88388f353..760d94865c 100644
--- a/include/tpm.h
+++ b/include/tpm.h
@@ -84,9 +84,12 @@ enum tpm_capability_areas {
};
#define TPM_NV_PER_GLOBALLOCK (1U << 15)
+#define TPM_NV_PER_PPREAD (1U << 16)
#define TPM_NV_PER_PPWRITE (1U << 0)
#define TPM_NV_PER_READ_STCLEAR (1U << 31)
#define TPM_NV_PER_WRITE_STCLEAR (1U << 14)
+#define TPM_NV_PER_WRITEDEFINE (1U << 13)
+#define TPM_NV_PER_WRITEALL (1U << 12)
enum {
TPM_PUBEK_SIZE = 256,
@@ -651,4 +654,16 @@ uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type);
uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t
pubkey_digest[20], uint32_t *handle);
#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
+
+/**
+ * Read random bytes from the TPM RNG. The implementation deals with the fact
+ * that the TPM may legally return fewer bytes than requested by retrying
+ * until @p count bytes have been received.
+ *
+ * @param data output buffer for the random bytes
+ * @param count size of output buffer
+ * @return return code of the operation
+ */
+uint32_t tpm_get_random(void *data, uint32_t count);
+
#endif /* __TPM_H */
diff --git a/lib/tpm.c b/lib/tpm.c
index d1cf5a8a16..c8bf06178f 100644
--- a/lib/tpm.c
+++ b/lib/tpm.c
@@ -92,6 +92,7 @@ int pack_byte_string(uint8_t *str, size_t size, const char *format, ...)
break;
default:
debug("Couldn't recognize format string\n");
+ va_end(args);
return -1;
}
@@ -170,8 +171,10 @@ int unpack_byte_string(const uint8_t *str, size_t size, const char *format, ...)
return -1;
}
- if (offset + length > size)
+ if (offset + length > size) {
+ va_end(args);
return -1;
+ }
switch (*format) {
case 'b':
@@ -607,14 +610,24 @@ uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags)
0x0, 0x0, 0x0, 0x4, /* subcap size */
0x0, 0x0, 0x1, 0x8, /* subcap value */
};
+ const size_t data_size_offset = TPM_HEADER_SIZE;
+ const size_t data_offset = TPM_HEADER_SIZE + sizeof (uint32_t);
uint8_t response[COMMAND_BUFFER_SIZE];
size_t response_length = sizeof(response);
uint32_t err;
+ uint32_t data_size;
err = tpm_sendrecv_command(command, response, &response_length);
if (err)
return err;
- memcpy(pflags, response + TPM_HEADER_SIZE, sizeof(*pflags));
+ if (unpack_byte_string(response, response_length, "d",
+ data_size_offset, &data_size))
+ return TPM_LIB_ERROR;
+ if (data_size < sizeof(*pflags))
+ return TPM_LIB_ERROR;
+ if (unpack_byte_string(response, response_length, "s",
+ data_offset, pflags, sizeof(*pflags)))
+ return TPM_LIB_ERROR;
return 0;
}
@@ -1039,3 +1052,46 @@ uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t
#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
#endif /* CONFIG_TPM_AUTH_SESSIONS */
+
+uint32_t tpm_get_random(void *data, uint32_t count)
+{
+ const uint8_t command[14] = {
+ 0x0, 0xc1, /* TPM_TAG */
+ 0x0, 0x0, 0x0, 0xe, /* parameter size */
+ 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */
+ };
+ const size_t length_offset = 10;
+ const size_t data_size_offset = 10;
+ const size_t data_offset = 14;
+ uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+ size_t response_length = sizeof(response);
+ uint32_t data_size;
+ uint8_t *out = data;
+
+ while (count > 0) {
+ uint32_t this_bytes = min((size_t)count,
+ sizeof (response) - data_offset);
+ uint32_t err;
+
+ if (pack_byte_string(buf, sizeof(buf), "sd",
+ 0, command, sizeof(command),
+ length_offset, this_bytes))
+ return TPM_LIB_ERROR;
+ err = tpm_sendrecv_command(buf, response, &response_length);
+ if (err)
+ return err;
+ if (unpack_byte_string(response, response_length, "d",
+ data_size_offset, &data_size))
+ return TPM_LIB_ERROR;
+ if (data_size > count)
+ return TPM_LIB_ERROR;
+ if (unpack_byte_string(response, response_length, "s",
+ data_offset, out, data_size))
+ return TPM_LIB_ERROR;
+
+ count -= data_size;
+ out += data_size;
+ }
+
+ return 0;
+}