To add a string to your cmos.layout, you need to specify type 's': #start len type unused name 416 512 s 0 boot_devices With this patch you can do $ nvramtool -w boot_devices="(hd0,0);(hd2,1);(hd3)" And FILO will attempt to load a menu.lst from any of these devices in that order. The patch is not exactly pretty, but a cleaner solution might have resulted in a complete rewrite of the tool, which I did not want. Signed-off-by: Stefan Reinauer <stepan@coresystems.de> Acked-by: Joseph Smith <joe@settoplinux.org> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3613 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
		
			
				
	
	
		
			232 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			232 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*****************************************************************************\
 | 
						|
 * cmos_ops.c
 | 
						|
 *****************************************************************************
 | 
						|
 *  Copyright (C) 2002-2005 The Regents of the University of California.
 | 
						|
 *  Produced at the Lawrence Livermore National Laboratory.
 | 
						|
 *  Written by David S. Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>.
 | 
						|
 *  UCRL-CODE-2003-012
 | 
						|
 *  All rights reserved.
 | 
						|
 *
 | 
						|
 *  This file is part of nvramtool, a utility for reading/writing coreboot
 | 
						|
 *  parameters and displaying information from the coreboot table.
 | 
						|
 *  For details, see http://coreboot.org/nvramtool.
 | 
						|
 *
 | 
						|
 *  Please also read the file DISCLAIMER which is included in this software
 | 
						|
 *  distribution.
 | 
						|
 *
 | 
						|
 *  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) version 2, dated June 1991.
 | 
						|
 *
 | 
						|
 *  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 terms and
 | 
						|
 *  conditions of 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.,
 | 
						|
 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 | 
						|
\*****************************************************************************/
 | 
						|
 | 
						|
#include "common.h"
 | 
						|
#include "cmos_ops.h"
 | 
						|
#include "cmos_lowlevel.h"
 | 
						|
 | 
						|
static int prepare_cmos_op_common (const cmos_entry_t *e);
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
 * prepare_cmos_op_common
 | 
						|
 *
 | 
						|
 * Perform a few checks common to both reads and writes.
 | 
						|
 ****************************************************************************/
 | 
						|
static int prepare_cmos_op_common (const cmos_entry_t *e)
 | 
						|
 { int result;
 | 
						|
 | 
						|
   if (e->config == CMOS_ENTRY_RESERVED)
 | 
						|
      /* Access to reserved parameters is not permitted. */
 | 
						|
      return CMOS_OP_RESERVED;
 | 
						|
 | 
						|
   if ((result = verify_cmos_op(e->bit, e->length, e->config)) != OK)
 | 
						|
      return result;
 | 
						|
 | 
						|
   assert(e->length > 0);
 | 
						|
   return OK;
 | 
						|
 }
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
 * prepare_cmos_read
 | 
						|
 *
 | 
						|
 * The caller wishes to read a CMOS parameter represented by 'e'.  Perform
 | 
						|
 * sanity checking on 'e'.  If a problem was found with e, return an error
 | 
						|
 * code.  Else return OK.
 | 
						|
 ****************************************************************************/
 | 
						|
int prepare_cmos_read (const cmos_entry_t *e)
 | 
						|
 { int result;
 | 
						|
 | 
						|
   if ((result = prepare_cmos_op_common(e)) != OK)
 | 
						|
      return result;
 | 
						|
 | 
						|
   switch (e->config)
 | 
						|
    { case CMOS_ENTRY_ENUM:
 | 
						|
      case CMOS_ENTRY_HEX:
 | 
						|
      case CMOS_ENTRY_STRING:
 | 
						|
         break;
 | 
						|
 | 
						|
      default:
 | 
						|
         BUG();
 | 
						|
    }
 | 
						|
 | 
						|
   return OK;
 | 
						|
 }
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
 * prepare_cmos_write
 | 
						|
 *
 | 
						|
 * The caller wishes to set a CMOS parameter represented by 'e' to a value
 | 
						|
 * whose string representation is stored in 'value_str'.  Perform sanity
 | 
						|
 * checking on 'value_str'.  On error, return an error code.  Else store the
 | 
						|
 * numeric equivalent of 'value_str' in '*value' and return OK.
 | 
						|
 ****************************************************************************/
 | 
						|
int prepare_cmos_write (const cmos_entry_t *e, const char value_str[],
 | 
						|
                        unsigned long long *value)
 | 
						|
 { const cmos_enum_t *q;
 | 
						|
   unsigned long long out;
 | 
						|
   const char *p;
 | 
						|
   char *memory;
 | 
						|
   int negative, result, found_one;
 | 
						|
 | 
						|
   if ((result = prepare_cmos_op_common(e)) != OK)
 | 
						|
      return result;
 | 
						|
 | 
						|
   switch (e->config)
 | 
						|
    { case CMOS_ENTRY_ENUM:
 | 
						|
         /* Make sure the user's input corresponds to a valid option. */
 | 
						|
         for (q = first_cmos_enum_id(e->config_id), found_one = 0;
 | 
						|
              q != NULL;
 | 
						|
              q = next_cmos_enum_id(q))
 | 
						|
          { found_one = 1;
 | 
						|
 | 
						|
            if (!strncmp(q->text, value_str, CMOS_MAX_TEXT_LENGTH))
 | 
						|
               break;
 | 
						|
          }
 | 
						|
 | 
						|
         if (!found_one)
 | 
						|
            return CMOS_OP_NO_MATCHING_ENUM;
 | 
						|
 | 
						|
         if (q == NULL)
 | 
						|
            return CMOS_OP_BAD_ENUM_VALUE;
 | 
						|
 | 
						|
         out = q->value;
 | 
						|
         break;
 | 
						|
 | 
						|
      case CMOS_ENTRY_HEX:
 | 
						|
         /* See if the first character of 'value_str' (excluding any initial
 | 
						|
          * whitespace) is a minus sign.
 | 
						|
          */
 | 
						|
         for (p = value_str; isspace(*p); p++);
 | 
						|
         negative = (*p == '-');
 | 
						|
 | 
						|
         out = strtoull(value_str, (char **) &p, 0);
 | 
						|
 | 
						|
         if (*p)
 | 
						|
            return CMOS_OP_INVALID_INT;
 | 
						|
 | 
						|
         /* If we get this far, the user specified a valid integer.  However
 | 
						|
          * we do not currently support the use of negative numbers as CMOS
 | 
						|
          * parameter values.
 | 
						|
          */
 | 
						|
         if (negative)
 | 
						|
            return CMOS_OP_NEGATIVE_INT;
 | 
						|
 | 
						|
         break;
 | 
						|
 | 
						|
      case CMOS_ENTRY_STRING:
 | 
						|
	 if (e->length < (8 * strlen(value_str)))
 | 
						|
	    return CMOS_OP_VALUE_TOO_WIDE;
 | 
						|
	 memory = malloc(e->length / 8);
 | 
						|
         memset(memory, 0, e->length / 8);
 | 
						|
         strcpy(memory, value_str);
 | 
						|
         out = (unsigned long)memory;
 | 
						|
	 break;
 | 
						|
 | 
						|
      default:
 | 
						|
         BUG();
 | 
						|
    }
 | 
						|
 | 
						|
   if ((e->length < (8 * sizeof(*value))) &&
 | 
						|
       (out >= (1ull << e->length)))
 | 
						|
      return CMOS_OP_VALUE_TOO_WIDE;
 | 
						|
 | 
						|
   *value = out;
 | 
						|
   return OK;
 | 
						|
 }
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
 * cmos_checksum_read
 | 
						|
 *
 | 
						|
 * Read the checksum for the coreboot parameters stored in CMOS and return
 | 
						|
 * this value.
 | 
						|
 ****************************************************************************/
 | 
						|
uint16_t cmos_checksum_read (void)
 | 
						|
 { uint16_t lo, hi;
 | 
						|
 | 
						|
   /* The checksum is stored in a big-endian format. */
 | 
						|
   hi = cmos_read_byte(cmos_checksum_index);
 | 
						|
   lo = cmos_read_byte(cmos_checksum_index + 1);
 | 
						|
   return (hi << 8) + lo;
 | 
						|
 }
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
 * cmos_checksum_write
 | 
						|
 *
 | 
						|
 * Set the checksum for the coreboot parameters stored in CMOS to
 | 
						|
 * 'checksum'.
 | 
						|
 ****************************************************************************/
 | 
						|
void cmos_checksum_write (uint16_t checksum)
 | 
						|
 { unsigned char lo, hi;
 | 
						|
 | 
						|
   /* The checksum is stored in a big-endian format. */
 | 
						|
   hi = (unsigned char) (checksum >> 8);
 | 
						|
   lo = (unsigned char) (checksum & 0x00ff);
 | 
						|
   cmos_write_byte(cmos_checksum_index, hi);
 | 
						|
   cmos_write_byte(cmos_checksum_index + 1, lo);
 | 
						|
 }
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
 * cmos_checksum_compute
 | 
						|
 *
 | 
						|
 * Compute a checksum for the coreboot parameter values currently stored in
 | 
						|
 * CMOS and return this checksum.
 | 
						|
 ****************************************************************************/
 | 
						|
uint16_t cmos_checksum_compute (void)
 | 
						|
 { unsigned i, sum;
 | 
						|
 | 
						|
   sum = 0;
 | 
						|
 | 
						|
   for (i = cmos_checksum_start; i <= cmos_checksum_end; i++)
 | 
						|
      sum += cmos_read_byte(i);
 | 
						|
 | 
						|
   return ~((uint16_t) (sum & 0xffff));
 | 
						|
 }
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
 * cmos_checksum_verify
 | 
						|
 *
 | 
						|
 * Verify that the coreboot CMOS checksum is valid.  If checksum is not
 | 
						|
 * valid then print warning message and exit.
 | 
						|
 ****************************************************************************/
 | 
						|
void cmos_checksum_verify (void)
 | 
						|
 { uint16_t computed, actual;
 | 
						|
 | 
						|
   set_iopl(3);
 | 
						|
   computed = cmos_checksum_compute();
 | 
						|
   actual = cmos_checksum_read();
 | 
						|
   set_iopl(0);
 | 
						|
 | 
						|
   if (computed != actual)
 | 
						|
    { fprintf(stderr, "%s: Warning: Coreboot CMOS checksum is bad.\n",
 | 
						|
              prog_name);
 | 
						|
      exit(1);
 | 
						|
    }
 | 
						|
 }
 |