Add nvramtool -D option that allows taking cmos data from
[coreboot.git] / util / nvramtool / nvramtool.c
index e82d0ac9d8cd0ed7b91b3e9d8a47cde2e3ab1983..cb717513aed5a8eeff476bd74ed637abeb03d942 100644 (file)
  *  51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 \*****************************************************************************/
 
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
 #include "common.h"
 #include "opts.h"
 #include "lbtable.h"
@@ -38,6 +42,7 @@
 #include "cmos_lowlevel.h"
 #include "reg_expr.h"
 #include "hexdump.h"
+#include "cbfs.h"
 
 typedef void (*op_fn_t) (void);
 
@@ -92,7 +97,8 @@ static const hexdump_format_t cmos_dump_format =
  ****************************************************************************/
 int main(int argc, char *argv[])
 {
-       cmos_layout_get_fn_t fn;
+       void *cmos_default = NULL;
+       cmos_layout_get_fn_t fn = get_layout_from_cmos_table;
 
        parse_nvramtool_args(argc, argv);
 
@@ -100,8 +106,44 @@ int main(int argc, char *argv[])
                set_layout_filename(nvramtool_op_modifiers
                                    [NVRAMTOOL_MOD_USE_CMOS_LAYOUT_FILE].param);
                fn = get_layout_from_file;
-       } else
+       } else if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_OPT_TABLE].found) {
                fn = get_layout_from_cmos_table;
+       } else if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CBFS_FILE].found) {
+               open_cbfs(nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CBFS_FILE].param);
+               if (!nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].found) {
+                       cmos_default = cbfs_find_file("cmos.default", CBFS_COMPONENT_CMOS_DEFAULT, NULL);
+                       if (cmos_default == NULL) {
+                               fprintf(stderr, "Need a cmos.default in the CBFS image or separate cmos file (-D).\n");
+                               exit(1);
+                       }
+               }
+       }
+       if (nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].found) {
+               int fd;
+               struct stat fd_stat;
+               if ((fd = open(nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].param, O_RDWR | O_CREAT, 0666)) < 0) {
+                       fprintf(stderr, "Couldn't open '%s'\n", nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].param);
+                       exit(1);
+               }
+               if (fstat(fd, &fd_stat) == -1) {
+                       fprintf(stderr, "Couldn't stat '%s'\n", nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].param);
+                       exit(1);
+               }
+               if (fd_stat.st_size < 128) {
+                       lseek(fd, 127, SEEK_SET);
+                       write(fd, "\0", 1);
+                       fsync(fd);
+               }
+               cmos_default = mmap(NULL, 128, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+               if (cmos_default == MAP_FAILED) {
+                       fprintf(stderr, "Couldn't map '%s'\n", nvramtool_op_modifiers[NVRAMTOOL_MOD_USE_CMOS_FILE].param);
+                       exit(1);
+               }
+       }
+       if (cmos_default) {
+               select_hal(HAL_MEMORY, cmos_default);
+               fn = get_layout_from_cbfs_file;
+       }
 
        register_cmos_layout_get_fn(fn);
        op_fns[nvramtool_op.op] ();