diff --git a/cmd/fru.c b/cmd/fru.c
index d5e96cfe8984..3bbc4d272adb 100644
--- a/cmd/fru.c
+++ b/cmd/fru.c
@@ -31,9 +31,23 @@ static int do_fru_display(cmd_tbl_t *cmdtp, int flag, int argc,
 	return CMD_RET_SUCCESS;
 }
 
+static int do_fru_generate(cmd_tbl_t *cmdtp, int flag, int argc,
+			   char *const argv[])
+{
+	unsigned long addr;
+
+	if (argc < cmdtp->maxargs)
+		return CMD_RET_USAGE;
+
+	addr = simple_strtoul(argv[2], NULL, 16);
+
+	return fru_generate(addr, argv[3], argv[4], argv[5], argv[6]);
+}
+
 static cmd_tbl_t cmd_fru_sub[] = {
 	U_BOOT_CMD_MKENT(capture, 3, 0, do_fru_capture, "", ""),
 	U_BOOT_CMD_MKENT(display, 2, 0, do_fru_display, "", ""),
+	U_BOOT_CMD_MKENT(board_gen, 7, 0, do_fru_generate, "", ""),
 };
 
 static int do_fru(cmd_tbl_t *cmdtp, int flag, int argc,
@@ -58,11 +72,15 @@ static char fru_help_text[] =
 	"capture <addr> - Parse and capture FRU table present at address.\n"
 	"fru display - Displays content of FRU table that was captured using\n"
 	"              fru capture command\n"
+	"fru board_gen <addr> <manufacturer> <board name> <serial number>\n"
+	"              <part number> - Generate FRU format with board info\n"
+	"              area filled based on parameters. <addr> is pointing\n"
+	"              to place where FRU is generated.\n"
 	;
 #endif
 
 U_BOOT_CMD(
-	fru, 3, 1, do_fru,
+	fru, 7, 1, do_fru,
 	"FRU table info",
 	fru_help_text
 )
diff --git a/common/fru_ops.c b/common/fru_ops.c
index dd54bd9c0214..d9c00b12da03 100644
--- a/common/fru_ops.c
+++ b/common/fru_ops.c
@@ -58,6 +58,101 @@ static int fru_check_type_len(u8 type_len, u8 language, u8 *type)
 	return len;
 }
 
+/* Return len */
+static u8 fru_gen_type_len(u8 *addr, char *name)
+{
+	int len = strlen(name);
+	struct fru_board_info_member *member;
+
+	member = (struct fru_board_info_member *)addr;
+	member->type_len = FRU_TYPELEN_TYPE_ASCII8 << FRU_TYPELEN_TYPE_SHIFT;
+	member->type_len |= len;
+
+	debug("%lx/%lx: Add %s to 0x%lx (len 0x%x)\n", (ulong)addr,
+	      (ulong)&member->type_len,  name, (ulong)&member->name, len);
+	memcpy(&member->name, name, len);
+
+	/* Add +1 for type_len parameter */
+	return 1 + len;
+}
+
+int fru_generate(unsigned long addr, char *manufacturer, char *board_name,
+		 char *serial_no, char *part_no)
+{
+	struct fru_common_hdr *header = (struct fru_common_hdr *)addr;
+	struct fru_board_info_header *board_info;
+	u8 *member;
+	u8 len, pad, modulo;
+
+	header->version = 1; /* Only version 1.0 is supported now */
+	header->off_internal = 0; /* not present */
+	header->off_chassis = 0; /* not present */
+	header->off_board = (sizeof(*header)) / 8; /* Starting offset 8 */
+	header->off_product = 0; /* not present */
+	header->off_multirec = 0; /* not present */
+	header->pad = 0;
+	/*
+	 * This unsigned byte can be used to calculate a zero checksum
+	 * for the data area following the header. I.e. the modulo 256 sum of
+	 * the record data bytes plus the checksum byte equals zero.
+	 */
+	header->crc = 0; /* Clear before calculation */
+	header->crc = 0 - fru_checksum((u8 *)header, sizeof(*header));
+
+	/* board info is just right after header */
+	board_info = (void *)((u8 *)header + sizeof(*header));
+
+	debug("header %lx, board_info %lx\n", (ulong)header, (ulong)board_info);
+
+	board_info->ver = 1; /* 1.0 spec */
+	board_info->lang_code = 0; /* English */
+	board_info->time[0] = 0; /* unspecified */
+	board_info->time[1] = 0; /* unspecified */
+	board_info->time[2] = 0; /* unspecified */
+
+	/* Member fields are just after board_info header */
+	member = (u8 *)board_info + sizeof(*board_info);
+
+	len = fru_gen_type_len(member, manufacturer); /* Board Manufacturer */
+	member += len;
+	len = fru_gen_type_len(member, board_name); /* Board Product name */
+	member += len;
+	len = fru_gen_type_len(member, serial_no); /* Board Serial number */
+	member += len;
+	len = fru_gen_type_len(member, part_no); /* Board part number */
+	member += len;
+	len = fru_gen_type_len(member, "U-Boot generator"); /* File ID */
+	member += len;
+
+	*member++ = 0xc1; /* Indication of no more fields */
+
+	len = member - (u8 *)board_info; /* Find current length */
+	len += 1; /* Add checksum there too for calculation */
+
+	modulo = len % 8;
+
+	if (modulo) {
+		/* Do not fill last item which is checksum */
+		for (pad = 0; pad < 8 - modulo; pad++)
+			*member++ = 0;
+
+		/* Increase structure size */
+		len += 8 - modulo;
+	}
+
+	board_info->len = len / 8; /* Size in multiples of 8 bytes */
+
+	*member = 0; /* Clear before calculation */
+	*member = 0 - fru_checksum((u8 *)board_info, len);
+
+	debug("checksum %x(len %x)\n", *member, len);
+
+	env_set_hex("fru_addr", addr);
+	env_set_hex("filesize", len);
+
+	return 0;
+}
+
 static int fru_parse_board(unsigned long addr)
 {
 	u8 i, type;
diff --git a/include/fru.h b/include/fru.h
index 38fdfad409c4..09de266477d4 100644
--- a/include/fru.h
+++ b/include/fru.h
@@ -20,6 +20,18 @@ struct fru_common_hdr {
 
 #define FRU_BOARD_MAX_LEN	32
 
+struct __packed fru_board_info_header {
+	u8 ver;
+	u8 len;
+	u8 lang_code;
+	u8 time[3];
+};
+
+struct __packed fru_board_info_member {
+	u8 type_len;
+	u8 *name;
+};
+
 struct fru_board_data {
 	u8 ver;
 	u8 len;
@@ -58,6 +70,8 @@ struct fru_table {
 
 int fru_display(void);
 int fru_capture(unsigned long addr);
+int fru_generate(unsigned long addr, char *manufacturer, char *board_name,
+		 char *serial_no, char *part_no);
 
 extern struct fru_table fru_data;
 
