From a67aab70834fe28c34d4a1c9203f6f1b8462cc38 Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Sat, 27 Sep 2008 10:08:28 +0000 Subject: Add string support to nvramtool. 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 Acked-by: Joseph Smith git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3613 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- util/nvramtool/cmos_lowlevel.c | 73 +++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 19 deletions(-) (limited to 'util/nvramtool/cmos_lowlevel.c') diff --git a/util/nvramtool/cmos_lowlevel.c b/util/nvramtool/cmos_lowlevel.c index ab116797a2..9ad6891d0c 100644 --- a/util/nvramtool/cmos_lowlevel.c +++ b/util/nvramtool/cmos_lowlevel.c @@ -1,6 +1,5 @@ /*****************************************************************************\ * cmos_lowlevel.c - * $Id$ ***************************************************************************** * Copyright (C) 2002-2005 The Regents of the University of California. * Produced at the Lawrence Livermore National Laboratory. @@ -70,7 +69,7 @@ static inline unsigned char get_bits (unsigned long long value, unsigned bit, ****************************************************************************/ static inline void put_bits (unsigned char value, unsigned bit, unsigned nr_bits, unsigned long long *result) - { *result += (value & ((unsigned char) ((1 << nr_bits) - 1))) << bit; } + { *result += ((unsigned long long)(value & ((unsigned char) ((1 << nr_bits) - 1)))) << bit; } /**************************************************************************** * cmos_read @@ -79,21 +78,39 @@ static inline void put_bits (unsigned char value, unsigned bit, * and return this value. The I/O privilege level of the currently executing * process must be set appropriately. ****************************************************************************/ -unsigned long long cmos_read (unsigned bit, unsigned length) +unsigned long long cmos_read (const cmos_entry_t *e) { cmos_bit_op_location_t where; + unsigned bit = e->bit, length=e->length; unsigned next_bit, bits_left, nr_bits; - unsigned long long result; + unsigned long long result = 0; unsigned char value; - assert(!verify_cmos_op(bit, length)); + assert(!verify_cmos_op(bit, length, e->config)); result = 0; - for (next_bit = 0, bits_left = length; - bits_left; - next_bit += nr_bits, bits_left -= nr_bits) - { nr_bits = cmos_bit_op_strategy(bit + next_bit, bits_left, &where); - value = cmos_read_bits(&where, nr_bits); - put_bits(value, next_bit, nr_bits, &result); + if (e->config == CMOS_ENTRY_STRING) + { char *newstring = malloc((length+7)/8); + unsigned usize = (8 * sizeof(unsigned long long)); + + if(!newstring) { out_of_memory(); } + + for (next_bit = 0, bits_left = length; + bits_left; + next_bit += nr_bits, bits_left -= nr_bits) + { nr_bits = cmos_bit_op_strategy(bit + next_bit, bits_left>usize?usize:bits_left, &where); + value = cmos_read_bits(&where, nr_bits); + put_bits(value, next_bit % usize, nr_bits, &((unsigned long long *)newstring)[next_bit/usize]); + result = (unsigned long)newstring; + } + } + else + { for (next_bit = 0, bits_left = length; + bits_left; + next_bit += nr_bits, bits_left -= nr_bits) + { nr_bits = cmos_bit_op_strategy(bit + next_bit, bits_left, &where); + value = cmos_read_bits(&where, nr_bits); + put_bits(value, next_bit, nr_bits, &result); + } } return result; @@ -106,17 +123,32 @@ unsigned long long cmos_read (unsigned bit, unsigned length) * The I/O privilege level of the currently executing process must be set * appropriately. ****************************************************************************/ -void cmos_write (unsigned bit, unsigned length, unsigned long long value) +void cmos_write (const cmos_entry_t *e, unsigned long long value) { cmos_bit_op_location_t where; + unsigned bit = e->bit, length=e->length; unsigned next_bit, bits_left, nr_bits; - assert(!verify_cmos_op(bit, length)); + assert(!verify_cmos_op(bit, length, e->config)); - for (next_bit = 0, bits_left = length; - bits_left; - next_bit += nr_bits, bits_left -= nr_bits) - { nr_bits = cmos_bit_op_strategy(bit + next_bit, bits_left, &where); - cmos_write_bits(&where, nr_bits, get_bits(value, next_bit, nr_bits)); + if (e->config == CMOS_ENTRY_STRING) + { unsigned long long *data = (unsigned long long *)(unsigned long)value; + unsigned usize = (8 * sizeof(unsigned long long)); + + for (next_bit = 0, bits_left = length; + bits_left; + next_bit += nr_bits, bits_left -= nr_bits) + { nr_bits = cmos_bit_op_strategy(bit + next_bit, bits_left>usize?usize:bits_left, &where); + value = data[next_bit/usize]; + cmos_write_bits(&where, nr_bits, get_bits(value, next_bit % usize, nr_bits)); + } + } + else + { for (next_bit = 0, bits_left = length; + bits_left; + next_bit += nr_bits, bits_left -= nr_bits) + { nr_bits = cmos_bit_op_strategy(bit + next_bit, bits_left, &where); + cmos_write_bits(&where, nr_bits, get_bits(value, next_bit, nr_bits)); + } } } @@ -236,13 +268,16 @@ void set_iopl (int level) * wish to read or write. Perform sanity checking on 'bit' and 'length'. If * no problems were encountered, return OK. Else return an error code. ****************************************************************************/ -int verify_cmos_op (unsigned bit, unsigned length) +int verify_cmos_op (unsigned bit, unsigned length, cmos_entry_config_t config) { if ((bit >= (8 * CMOS_SIZE)) || ((bit + length) > (8 * CMOS_SIZE))) return CMOS_AREA_OUT_OF_RANGE; if (bit < (8 * CMOS_RTC_AREA_SIZE)) return CMOS_AREA_OVERLAPS_RTC; + if (config == CMOS_ENTRY_STRING) + return OK; + if (length > (8 * sizeof(unsigned long long))) return CMOS_AREA_TOO_WIDE; -- cgit v1.2.3