diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h index ae6883f..59729f5 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 955a008..b783b0d 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 aaddddd..d232f67 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 eacf171..5d440ce 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -7,6 +7,7 @@ #include #include +#include #include 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 79374b8..8b9932a 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 f88388f..760d948 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 d1cf5a8..c8bf061 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; +}