From 6dfd65f81fd060a85c961a84f85a286e8e96332c Mon Sep 17 00:00:00 2001 From: Bernhard Messerklinger Date: Thu, 28 Sep 2017 11:29:52 +0200 Subject: [PATCH 1/9] cmd/fdt.c align data buffer to avoid unaligned word access Since the compiler is free to place a char array to any address in memory (in this case the stack), also to a non word aligned address the function "fdt_prop_parse" runs into troubles upon it wants to write some (fdt32_t *) to such a variable (if it has been placed to a none word aligned address). To avoid this we tell the compiler to always align this scratchpad to a word aligned address. Signed-off-by: Bernhard Messerklinger Reviewed-by: Hannes Schmelzer Tested-by: Hannes Schmelzer Reviewed-by: Simon Glass --- cmd/fdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 */ From 8ccc2db6e84244e5cb57885dc9dfd7e752071b98 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 28 Sep 2017 06:35:15 -0600 Subject: [PATCH 2/9] dm: core: Correct address cast in dev_read_addr_ptr() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This currently causes a warning in sandbox and will not do the right thing: drivers/core/read.c: In function ‘dev_read_addr_ptr’: drivers/core/read.c:64:44: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] return (addr == FDT_ADDR_T_NONE) ? NULL : (void *)addr; Use map_sysmem() which is the correct way to convert an address to a pointer. Fixes: c131c8bca8 (dm: core: add dev_read_addr_ptr()) Signed-off-by: Simon Glass Reviewed-by: Philipp Tomsich Reviewed-by: Bin Meng Tested-by: Bin Meng Acked-by: Philipp Tomsich --- drivers/core/read.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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, From 35172cfee8b02e5f3b21de35255d9d80afa196a9 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Fri, 29 Sep 2017 08:53:53 -0400 Subject: [PATCH 3/9] sandbox: Add clrbits/setbits macros We borrow the macros for these functions from ARM and remove references to '__raw_'. Signed-off-by: Tom Rini --- arch/sandbox/include/asm/io.h | 57 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) 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); From 3fe3839acc4a5d9b1af9b2ab3884b0d3f2e23370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Tue, 3 Oct 2017 16:55:50 +0100 Subject: [PATCH 4/9] SPL: fix printing of image name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The maximum length of the name of the image is obviously not sizeof(), which is just the length of a pointer, but IH_NMLEN. fixes: 62cf11c0921a90c6bd62344f4bc069668e6c698c ("SPL: Limit image name print length") Signed-off-by: André Draszik Acked-by: Simon Glass --- common/spl/spl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 */ From e8155dfe33eb2b3e538e8717d6578c1d08651454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Tue, 3 Oct 2017 16:55:51 +0100 Subject: [PATCH 5/9] tpm: fix reading of permanent flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The offset of the permanent flags structure is in a different place in the response compared to what the code is doing, which gives us a completely useless result. Fix by replacing hand-crafted code with generic parser infrastructure. Signed-off-by: André Draszik Acked-by: Simon Glass --- lib/tpm.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/tpm.c b/lib/tpm.c index d1cf5a8..5659fa5 100644 --- a/lib/tpm.c +++ b/lib/tpm.c @@ -607,14 +607,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; } From 3c6050277b54f536e7effbe850dcc970a27387ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Tue, 3 Oct 2017 16:55:52 +0100 Subject: [PATCH 6/9] tpm: add tpm_get_random() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a function to obtain random data from the TPM. Signed-off-by: André Draszik Added commit message, add cast to min() Signed-off-by: Simon Glass Acked-by: Simon Glass --- include/tpm.h | 12 ++++++++++++ lib/tpm.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/include/tpm.h b/include/tpm.h index f88388f..2a7528d 100644 --- a/include/tpm.h +++ b/include/tpm.h @@ -651,4 +651,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 5659fa5..d21bbcf 100644 --- a/lib/tpm.c +++ b/lib/tpm.c @@ -1049,3 +1049,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; +} From 1259f778c9b419f02e2c155996b2d15ff262901e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Tue, 3 Oct 2017 16:55:53 +0100 Subject: [PATCH 7/9] tpm: add more useful NV storage permission flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TPM_NV_PER_PPREAD: physical presence needed for reading TPM_NV_PER_WRITEDEFINE: persistent write lock by writing size 0 TPM_NV_PER_WRITEALL: write in one go Signed-off-by: André Draszik Acked-by: Simon Glass --- include/tpm.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/tpm.h b/include/tpm.h index 2a7528d..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, From 9d0c5fee29c30a361309514459e88e401f292532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Tue, 3 Oct 2017 16:55:54 +0100 Subject: [PATCH 8/9] tpm: add more missing va_end() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While commit 36d35345b1f6 ("tpm: add missing va_end") added some missing calls to va_end(), it missed a few places. Signed-off-by: André Draszik Acked-by: Simon Glass --- lib/tpm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/tpm.c b/lib/tpm.c index d21bbcf..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': From afc1a78a0bd5db69f72db1dfa07b4a37a54343f6 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 9 Nov 2017 13:44:28 +0200 Subject: [PATCH 9/9] dm: core: fix member name in ofnode_union documentation Fixes: 4984de2baaa ("dm: core: Add ofnode to represent device tree nodes") Cc: Simon Glass Signed-off-by: Baruch Siach Reviewed-by: Simon Glass --- include/dm/ofnode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 {