[coreboot-gerrit] Patch set updated for filo: dd51816 Add flashupdate command
Patrick Georgi (patrick@georgi-clan.de)
gerrit at coreboot.org
Fri Jun 13 13:53:20 CEST 2014
Patrick Georgi (patrick at georgi-clan.de) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/5988
-gerrit
commit dd51816080264c2719781ffc5fb40b4de2b0b3d2
Author: Patrick Georgi <patrick.georgi at secunet.com>
Date: Tue Jul 19 16:40:06 2011 +0200
Add flashupdate command
This command allows the user to load a coreboot image, configure its
cmos.default file and write it to flash, all from FILO.
Change-Id: Ia011deb64bcf75aebe8b67554ad9d9738d90fe59
Signed-off-by: Patrick Georgi <patrick.georgi at secunet.com>
---
Config.in | 15 ++-
Makefile | 1 +
flashupdate/Makefile.inc | 29 +++++
flashupdate/flashrom-bridge.c | 73 +++++++++++
flashupdate/flashupdate.c | 277 ++++++++++++++++++++++++++++++++++++++++++
main/grub/builtins.c | 19 ++-
x86/ldscript | 6 +-
7 files changed, 413 insertions(+), 7 deletions(-)
diff --git a/Config.in b/Config.in
index cc48bd3..d9f977a 100644
--- a/Config.in
+++ b/Config.in
@@ -189,8 +189,7 @@ config FLASHROM_LOCKDOWN
default n
help
Enable system flash memory write protections and lock them down prior
- starting the kernel. Flash memory lockdown can be disabled per boot
- entry with the new command 'flashrom_unlock'.
+ starting the kernel.
NOTE: Only supported on selected hardware:
@@ -199,6 +198,18 @@ config FLASHROM_LOCKDOWN
o Intel Cougar Point / Panther Point PCH (FWH + SPI)
o AMD SB600 (SPI by locking the flash chip itself)
+config FLASHROM_UNLOCK
+ bool "Provide flashrom_unlock command"
+ default n
+ depends on FLASHROM_LOCKDOWN
+ help
+ FlashROM lockdown can be disabled per boot entry with the new
+ command 'flashrom_unlock'.
+
+config FLASHUPDATE
+ bool "add flashrom utility to FILO"
+ default y
+
endmenu
menu "Filesystems"
diff --git a/Makefile b/Makefile
index 46010b3..570bd87 100644
--- a/Makefile
+++ b/Makefile
@@ -101,6 +101,7 @@ CFLAGS += $(call cc-option, -fno-stack-protector,)
LIBS := $(LIBPAYLOAD) $(LIBGCC)
+SUBDIRS-$(CONFIG_USE_GRUB) += flashupdate/
SUBDIRS-y += main/ fs/ drivers/
SUBDIRS-y += $(ARCHDIR-y)/
diff --git a/flashupdate/Makefile.inc b/flashupdate/Makefile.inc
new file mode 100644
index 0000000..319add3
--- /dev/null
+++ b/flashupdate/Makefile.inc
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2011 secunet AG
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+LIBFLASHROM_PREFIX ?= $(obj)/libflashrom
+LIBFLASHROM = $(LIBFLASHROM_PREFIX)/lib/libflashrom.a
+INCFLASHROM = $(LIBFLASHROM_PREFIX)/include
+
+ifeq ($(CONFIG_FLASHUPDATE),y)
+CPPFLAGS += -I$(INCFLASHROM)
+LIBS += $(LIBFLASHROM)
+endif
+
+TARGETS-$(CONFIG_FLASHUPDATE) += flashupdate/flashupdate.o
+TARGETS-$(CONFIG_FLASHUPDATE) += flashupdate/flashrom-bridge.o
diff --git a/flashupdate/flashrom-bridge.c b/flashupdate/flashrom-bridge.c
new file mode 100644
index 0000000..0940389
--- /dev/null
+++ b/flashupdate/flashrom-bridge.c
@@ -0,0 +1,73 @@
+#include <stdarg.h>
+#include <string.h>
+
+#include "flashchips.h"
+#include "flash.h"
+#include "programmer.h"
+
+int new_rom_size;
+void *new_rom_data;
+
+int old_rom_size;
+void *old_rom_data;
+
+// for flashrom
+int print(int type, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
+int print(int type, const char *fmt, ...)
+{
+#ifdef DEBUG
+ if (type > MSG_INFO) return 0;
+ int ret;
+ va_list args;
+ va_start(args, fmt);
+ ret = vprintf(fmt, args);
+ va_end(args);
+ return ret;
+#else
+ return 0;
+#endif
+}
+
+/* returned memory must be freed by caller */
+char *flashbuses_to_text(enum chipbustype bustype)
+{
+ return strdup("Unknown");
+}
+
+int read_buf_from_file(unsigned char *buf, unsigned long size, const char *filename)
+{
+ // we need at least enough space for our image.
+ if (size < new_rom_size)
+ return 1;
+
+ // top-align our image into the chip
+ memcpy(buf + size - new_rom_size, new_rom_data, new_rom_size);
+
+ return 0;
+}
+
+int read_flash_to_file(struct flashctx *flash, const char *filename)
+{
+ int ret = 0;
+ unsigned long size = flash->total_size * 1024;
+ if (size > old_rom_size) {
+ msg_cerr("old rom buffer not large enough for flash\n");
+ ret = 1;
+ goto out_free;
+ }
+
+ if (!flash->read) {
+ msg_cerr("No read function available for this flash chip.\n");
+ ret = 1;
+ goto out_free;
+ }
+ if (flash->read(flash, old_rom_data, 0, size)) {
+ msg_cerr("Read operation failed!\n");
+ ret = 1;
+ goto out_free;
+ }
+
+out_free:
+ return ret;
+}
+
diff --git a/flashupdate/flashupdate.c b/flashupdate/flashupdate.c
new file mode 100644
index 0000000..c0f337d
--- /dev/null
+++ b/flashupdate/flashupdate.c
@@ -0,0 +1,277 @@
+#include <stdlib.h>
+#include <getopt.h>
+#include <libpayload.h>
+#include <coreboot_tables.h>
+#include <cbfs.h>
+#include <grub/shared.h>
+#include <fs.h>
+#include <pci/pci.h>
+
+/* flashrom defines */
+#define CONFIG_INTERNAL 1
+#include "flashchips.h"
+#include "flash.h"
+#include "programmer.h"
+
+extern int new_rom_size;
+extern void *new_rom_data;
+
+struct flashctx flashchip;
+
+static void beep_success()
+{
+ int i;
+ for (i = 0; i < 5; i++) {
+ speaker_tone(440, 200); mdelay(300);
+ speaker_tone(660, 200); mdelay(300);
+ speaker_tone(880, 200); mdelay(300);
+ mdelay(3*1000);
+ }
+}
+
+static void beep_fail()
+{
+ int i;
+ for (i = 0; i < 5; i++) {
+ speaker_tone(1200, 200); mdelay(300);
+ speaker_tone( 660, 200); mdelay(300);
+ mdelay(3*1000);
+ }
+}
+
+static int init_flash(const char* flashtype)
+{
+ int j;
+ verbose++;
+ if (programmer_init(PROGRAMMER_INTERNAL, NULL)) {
+ grub_printf("Could not initialize programmer\n");
+ return -1;
+ }
+ for (j = 0; j < registered_programmer_count; j++) {
+ int current_chip = -1;
+ do {
+ current_chip = probe_flash(®istered_programmers[j], ++current_chip, &flashchip, 0);
+ if ((current_chip != -1) && ((flashtype == NULL) || (strcasecmp(flashchip.name, flashtype) == 0))) {
+ return 0;
+ }
+ } while (current_chip != -1);
+ }
+
+ grub_printf("Could not find flash chip\n");
+ return -1;
+}
+
+static int write_flash(void *imgdata, int size)
+{
+ return doit(&flashchip, 1, imgdata, 0, 1, 0, 1);
+}
+
+static int test_id_section(void *romarea, unsigned int romsize, int offset, char **vendor, char **model, char **version)
+{
+ /* data[-1]: romsize
+ data[-2]: offset top-of-rom to board model
+ data[-3]: offset top-of-rom to board vendor
+ data[-4]: offset top-of-rom to build version */
+ unsigned int *data = romarea+romsize-offset;
+ *version = romarea+romsize-data[-4];
+ *vendor = romarea+romsize-data[-3];
+ *model = romarea+romsize-data[-2];
+ /* Assume that data[-1] matches filesize, and that vendor and model are laid out without extra space.
+ DO NOT assume that model aligns to the offsets, there may be future additions. */
+ return ((data[-1] == romsize) && (*vendor+strnlen(*vendor, data[-2])+1 == *model));
+}
+
+int flashupdate_func(char *arg, int flags)
+{
+ int result = -1;
+ int force = 0;
+ char *chiptype = NULL;
+ char *vendor = NULL;
+ char *board = NULL;
+ char *region = NULL;
+
+ char **argv;
+ int argc = to_argc_argv(arg, &argv);
+
+ new_rom_data = NULL;
+
+ char opt;
+ optreset = optind = 1;
+ while ((opt = getopt(argc, argv, "fc:v:b:i:")) != -1) {
+ switch (opt) {
+ case 'f':
+ force = 1;
+ break;
+ case 'c':
+ chiptype = optarg;
+ break;
+ case 'v':
+ vendor = optarg;
+ break;
+ case 'b':
+ board = optarg;
+ break;
+ case 'i':
+ region = optarg;
+ break;
+ default:
+ grub_printf("unsupported option -%c.\n", opt);
+ goto out;
+ break;
+ }
+ }
+
+ if (optind >= argc) {
+ grub_printf("No filename specified.\n");
+ goto out;
+ }
+ const char *filename = argv[optind];
+
+ if (vendor && board &&
+ ((strcmp(vendor, cb_mb_vendor_string(lib_sysinfo.mainboard)) != 0) ||
+ (strcmp(board, cb_mb_part_string(lib_sysinfo.mainboard)) != 0))) {
+ /* since flashupdate semantics is: iff board matches, write flash;
+ it's a success not to flash on another board. */
+ result = 0;
+ goto out;
+ }
+
+ if (region) {
+ register_include_arg(region);
+ layout_use_ifd();
+ }
+
+ /* Step 0: Init programmer/flash to find out if we _can_ flash (we should) */
+ if (init_flash(chiptype) == -1) {
+ grub_printf("Could not initialize flash programmer.\n");
+ goto out;
+ }
+
+ /* Step 1: read requested image file */
+ if (!file_open(filename)) {
+ grub_printf("Could not open file '%s'\n", filename);
+ goto out;
+ }
+
+ /* 16K of extra space, since we don't have feof() */
+ new_rom_size = flashchip.total_size * 1024 + 16384;
+ new_rom_data = malloc(new_rom_size);
+ if (new_rom_data == NULL) {
+ grub_printf("Could not allocate memory.\n");
+ goto out;
+ }
+ void *readbuf = new_rom_data;
+ int len;
+ grub_printf("Loading image file... ");
+ while ((len = file_read(readbuf, 16384)) != 0) {
+ readbuf += len;
+ /* We can abort if we cut into the last 16K:
+ * it's more than the flash is able to carry
+ */
+ if (readbuf - new_rom_data > new_rom_size - 16384) {
+ file_close();
+ grub_printf("File too large for flash\n");
+ goto out;
+ }
+ }
+ new_rom_size = readbuf - new_rom_data;
+ file_close();
+ grub_printf("done\n");
+
+ /* retarget all CBFS accesses to new image */
+ setup_cbfs_from_ram(new_rom_data, new_rom_size);
+
+ /* Step 2: Check Board IDs (that we work on the right image) */
+ const char *cur_version = lib_sysinfo.cb_version;
+ const char *cur_vendor = cb_mb_vendor_string(lib_sysinfo.mainboard);
+ const char *cur_board = cb_mb_part_string(lib_sysinfo.mainboard);
+
+ /* Step 2a: check if this is a coreboot image by looking for a CBFS master header */
+ if (get_cbfs_header() != 0xffffffff) {
+ /* Step 2b: look for .id section in new ROM */
+ /* There are currently two locations where .id can reside: top-0x10 and top-0x80. There's
+ no indicator which one is used in any given image, though it should be stable on any given
+ board. As a heuristic, we can check if the data is sane at each location. */
+ char *new_vendor;
+ char *new_board;
+ char *new_version;
+ if (!test_id_section(new_rom_data, new_rom_size, 0x10, &new_vendor, &new_board, &new_version))
+ if (!test_id_section(new_rom_data, new_rom_size, 0x80, &new_vendor, &new_board, &new_version)) {
+ grub_printf("Could not detect if file supports this system.\n");
+ goto out;
+ }
+ if ((strcmp(cur_vendor, new_vendor) != 0) || (strcmp(cur_board, new_board) != 0)) {
+ grub_printf("File (%s %s) seems to be incompatible with current system (%s %s).\n",
+ new_vendor, new_board, cur_vendor, cur_board);
+ goto out;
+ }
+
+ /* Step 3: Check image version (so that we don't reflash the same image again and again) */
+ if (strcmp(cur_version, new_version) == 0) {
+ grub_printf("No need to update to the same version '%s'.\n", cur_version);
+ /* TODO: exit successfully. right? */
+ result = 0;
+ goto out;
+ }
+
+ /* Step 4: Merge current CMOS data with cmos.defaults */
+ /* Step 4a: Load new CMOS data */
+ void *cmos_defaults = cbfs_find_file("cmos.default", CBFS_COMPONENT_CMOS_DEFAULT);
+ void *cmos_layout = cbfs_find_file("cmos_layout.bin", CBFS_COMPONENT_CMOS_LAYOUT);
+ /* Step 4a1: Point use_mem to cmos.default. */
+ mem_accessor_base = cmos_defaults;
+ if (cmos_defaults && cmos_layout) {
+ /* Step 4b: Check if current CMOS data is valid. */
+ if (options_checksum_valid(use_nvram)) {
+ /* Step 4c: Iterate over current CMOS data */
+ struct cb_cmos_entries *cmos_entry = first_cmos_entry(get_system_option_table());
+ do {
+ /* Step 4c1: Attempt to update new CMOS data with current values. Ignore failures */
+ char *val = NULL;
+ get_option_as_string(use_nvram, get_system_option_table(), &val, cmos_entry->name);
+ if (val) {
+ set_option_from_string(use_mem, cmos_layout, val, cmos_entry->name);
+ }
+ } while (cmos_entry = next_cmos_entry(cmos_entry));
+ }
+
+ /* Step 5: Write merged CMOS image to CMOS */
+ /* TODO: do we need to skip 0x32 (RTC century)? */
+ int i;
+ for (i = 14; i < 256; i++)
+ nvram_write(((u8*)cmos_defaults)[i], i);
+
+ /* Step 6: Set cmos_defaults_loaded=no in CMOS data using new layout */
+ set_option_from_string(use_nvram, cmos_layout, "No", "cmos_defaults_loaded");
+
+ /* Step 6a: Set cmos_defaults_loaded=Yes in cmos.default in ROM image. */
+ set_option_from_string(use_mem, cmos_layout, "Yes", "cmos_defaults_loaded");
+ }
+ } else {
+ if (!force) {
+ grub_printf("This is a not a coreboot image. Aborting.\n");
+ goto out;
+ }
+ }
+
+ grub_printf("Writing image to flash, please wait.\n");
+ /* Step 7: Flash image */
+ if (write_flash(new_rom_data, new_rom_size) == 0) {
+ grub_printf("Flash was updated successfully.\n");
+ result = 0;
+ beep_success();
+ } else {
+ grub_printf("WARNING: Error while updating flash!!\n");
+ beep_fail();
+ }
+
+ /* success */
+ programmer_shutdown();
+
+out:
+ if (new_rom_data) free(new_rom_data);
+ new_rom_data = NULL;
+ if (argv) free(argv);
+ return result;
+}
+
diff --git a/main/grub/builtins.c b/main/grub/builtins.c
index f77a21a..8ebb829 100644
--- a/main/grub/builtins.c
+++ b/main/grub/builtins.c
@@ -549,7 +549,7 @@ static struct builtin builtin_find = {
};
#endif
-#ifdef CONFIG_FLASHROM_LOCKDOWN
+#ifdef CONFIG_FLASHROM_UNLOCK
/* flashrom_unlock */
/* Disable lockdown of flash memory on boot */
static int flashrom_unlock_func(char *arg, int flags)
@@ -568,6 +568,18 @@ static struct builtin builtin_flashrom_unlock = {
};
#endif
+#ifdef CONFIG_FLASHUPDATE
+int flashupdate_func(char *arg, int flags);
+
+static struct builtin builtin_flashupdate = {
+ "flashupdate",
+ flashupdate_func,
+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+ "flashupdate DEVICE",
+ "Update flash ROM from a file loaded from DEVICE (selected by the user)."
+};
+#endif
+
/* help */
#define MAX_SHORT_DOC_LEN 39
#define MAX_LONG_DOC_LEN 66
@@ -1924,9 +1936,12 @@ struct builtin *builtin_table[] = {
#ifdef CONFIG_EXPERIMENTAL
&builtin_find,
#endif
-#ifdef CONFIG_FLASHROM_LOCKDOWN
+#ifdef CONFIG_FLASHROM_UNLOCK
&builtin_flashrom_unlock,
#endif
+#ifdef CONFIG_FLASHUPDATE
+ &builtin_flashupdate,
+#endif
&builtin_help,
&builtin_hiddenmenu,
&builtin_initrd,
diff --git a/x86/ldscript b/x86/ldscript
index b260c51..f701d37 100644
--- a/x86/ldscript
+++ b/x86/ldscript
@@ -26,9 +26,9 @@ OUTPUT_ARCH(i386)
ENTRY(entry)
-/* 1024KB heap and 64KB stack */
-HEAP_SIZE = 1 * 1024 * 1024;
-STACK_SIZE = 64 * 1024;
+/* 96MB heap and 256KB stack */
+HEAP_SIZE = 96 * 1024 * 1024;
+STACK_SIZE = 256 * 1024;
SECTIONS
{
More information about the coreboot-gerrit
mailing list