X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=util%2Fnvramtool%2Fcmos_lowlevel.c;h=58494f9c5849bdf1f45024bb555f3c6be6b37714;hb=533ec00689d5affb283ea1a07c978972441deeba;hp=9ad6891d0c4d617a84e865186bbe48af7e277c86;hpb=a67aab70834fe28c34d4a1c9203f6f1b8462cc38;p=coreboot.git diff --git a/util/nvramtool/cmos_lowlevel.c b/util/nvramtool/cmos_lowlevel.c index 9ad6891d0..58494f9c5 100644 --- a/util/nvramtool/cmos_lowlevel.c +++ b/util/nvramtool/cmos_lowlevel.c @@ -25,29 +25,51 @@ * * 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. + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. \*****************************************************************************/ -#include +#if defined(__FreeBSD__) +#include +#include +#endif + #include "common.h" #include "cmos_lowlevel.h" -typedef struct - { unsigned byte_index; - unsigned bit_offset; - } -cmos_bit_op_location_t; - -static unsigned cmos_bit_op_strategy (unsigned bit, unsigned bits_left, - cmos_bit_op_location_t *where); -static unsigned char cmos_read_bits (const cmos_bit_op_location_t *where, - unsigned nr_bits); -static void cmos_write_bits (const cmos_bit_op_location_t *where, - unsigned nr_bits, unsigned char value); -static unsigned char get_bits (unsigned long long value, unsigned bit, - unsigned nr_bits); -static void put_bits (unsigned char value, unsigned bit, unsigned nr_bits, - unsigned long long *result); +/* Hardware Abstraction Layer: lowlevel byte-wise write access */ + +extern cmos_access_t cmos_hal, memory_hal; +static cmos_access_t *current_access = &cmos_hal; + +void select_hal(hal_t hal, void *data) +{ + switch(hal) { + case HAL_CMOS: + current_access = &cmos_hal; + break; + case HAL_MEMORY: + current_access = &memory_hal; + break; + } + current_access->init(data); +} + +/* Bit-level access */ +typedef struct { + unsigned byte_index; + unsigned bit_offset; +} cmos_bit_op_location_t; + +static unsigned cmos_bit_op_strategy(unsigned bit, unsigned bits_left, + cmos_bit_op_location_t * where); +static unsigned char cmos_read_bits(const cmos_bit_op_location_t * where, + unsigned nr_bits); +static void cmos_write_bits(const cmos_bit_op_location_t * where, + unsigned nr_bits, unsigned char value); +static unsigned char get_bits(unsigned long long value, unsigned bit, + unsigned nr_bits); +static void put_bits(unsigned char value, unsigned bit, unsigned nr_bits, + unsigned long long *result); /**************************************************************************** * get_bits @@ -55,9 +77,11 @@ static void put_bits (unsigned char value, unsigned bit, unsigned nr_bits, * Extract a value 'nr_bits' bits wide starting at bit position 'bit' from * 'value' and return the result. It is assumed that 'nr_bits' is at most 8. ****************************************************************************/ -static inline unsigned char get_bits (unsigned long long value, unsigned bit, - unsigned nr_bits) - { return (value >> bit) & ((unsigned char) ((1 << nr_bits) - 1)); } +static inline unsigned char get_bits(unsigned long long value, unsigned bit, + unsigned nr_bits) +{ + return (value >> bit) & ((unsigned char)((1 << nr_bits) - 1)); +} /**************************************************************************** * put_bits @@ -67,9 +91,12 @@ static inline unsigned char get_bits (unsigned long long value, unsigned bit, * positions in 'result' where the result is stored are assumed to be * initially zero. ****************************************************************************/ -static inline void put_bits (unsigned char value, unsigned bit, - unsigned nr_bits, unsigned long long *result) - { *result += ((unsigned long long)(value & ((unsigned char) ((1 << nr_bits) - 1)))) << bit; } +static inline void put_bits(unsigned char value, unsigned bit, + unsigned nr_bits, unsigned long long *result) +{ + *result += ((unsigned long long)(value & + ((unsigned char)((1 << nr_bits) - 1)))) << bit; +} /**************************************************************************** * cmos_read @@ -78,43 +105,48 @@ 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 (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 = 0; - unsigned char value; - - assert(!verify_cmos_op(bit, length, e->config)); - result = 0; - - 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; - } +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 = 0; + unsigned char value; + + assert(!verify_cmos_op(bit, length, e->config)); + result = 0; + + if (e->config == CMOS_ENTRY_STRING) { + char *newstring = calloc(1, (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; +} /**************************************************************************** * cmos_write @@ -123,34 +155,38 @@ unsigned long long cmos_read (const cmos_entry_t *e) * The I/O privilege level of the currently executing process must be set * appropriately. ****************************************************************************/ -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, e->config)); - - 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)); - } - } - } +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, e->config)); + + 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)); + } + } +} /**************************************************************************** * cmos_read_byte @@ -162,23 +198,10 @@ void cmos_write (const cmos_entry_t *e, unsigned long long value) * Note: the first 14 bytes of nonvolatile RAM provide an interface to the * real time clock. ****************************************************************************/ -unsigned char cmos_read_byte (unsigned index) - { unsigned short port_0, port_1; - - assert(!verify_cmos_byte_index(index)); - - if (index < 128) - { port_0 = 0x70; - port_1 = 0x71; - } - else - { port_0 = 0x72; - port_1 = 0x73; - } - - outb(index, port_0); - return inb(port_1); - } +unsigned char cmos_read_byte(unsigned index) +{ + return current_access->read(index); +} /**************************************************************************** * cmos_write_byte @@ -190,23 +213,10 @@ unsigned char cmos_read_byte (unsigned index) * real time clock. Writing to any of these bytes will therefore * affect its functioning. ****************************************************************************/ -void cmos_write_byte (unsigned index, unsigned char value) - { unsigned short port_0, port_1; - - assert(!verify_cmos_byte_index(index)); - - if (index < 128) - { port_0 = 0x70; - port_1 = 0x71; - } - else - { port_0 = 0x72; - port_1 = 0x73; - } - - outb(index, port_0); - outb(value, port_1); - } +void cmos_write_byte(unsigned index, unsigned char value) +{ + current_access->write(index, value); +} /**************************************************************************** * cmos_read_all @@ -214,15 +224,16 @@ void cmos_write_byte (unsigned index, unsigned char value) * Read all contents of CMOS memory into array 'data'. The first 14 bytes of * 'data' are set to zero since this corresponds to the real time clock area. ****************************************************************************/ -void cmos_read_all (unsigned char data[]) - { unsigned i; +void cmos_read_all(unsigned char data[]) +{ + unsigned i; - for (i = 0; i < CMOS_RTC_AREA_SIZE; i++) - data[i] = 0; + for (i = 0; i < CMOS_RTC_AREA_SIZE; i++) + data[i] = 0; - for (; i < CMOS_SIZE; i++) - data[i] = cmos_read_byte(i); - } + for (; i < CMOS_SIZE; i++) + data[i] = cmos_read_byte(i); +} /**************************************************************************** * cmos_write_all @@ -231,12 +242,13 @@ void cmos_read_all (unsigned char data[]) * bytes of 'data' are ignored since this corresponds to the real time clock * area. ****************************************************************************/ -void cmos_write_all (unsigned char data[]) - { unsigned i; +void cmos_write_all(unsigned char data[]) +{ + unsigned i; - for (i = CMOS_RTC_AREA_SIZE; i < CMOS_SIZE; i++) - cmos_write_byte(i, data[i]); - } + for (i = CMOS_RTC_AREA_SIZE; i < CMOS_SIZE; i++) + cmos_write_byte(i, data[i]); +} /**************************************************************************** * set_iopl @@ -247,17 +259,10 @@ void cmos_write_all (unsigned char data[]) * interrupts while executing in user space. Messing with the I/O privilege * level is therefore somewhat dangerous. ****************************************************************************/ -void set_iopl (int level) - { assert((level >= 0) && (level <= 3)); - - if (iopl(level)) - { fprintf(stderr, - "%s: iopl() system call failed. You must be root to do " - "this.\n", - prog_name); - exit(1); - } - } +void set_iopl(int level) +{ + current_access->set_iopl(level); +} /**************************************************************************** * verify_cmos_op @@ -268,21 +273,22 @@ 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, cmos_entry_config_t config) - { if ((bit >= (8 * CMOS_SIZE)) || ((bit + length) > (8 * CMOS_SIZE))) - return CMOS_AREA_OUT_OF_RANGE; +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 (bit < (8 * CMOS_RTC_AREA_SIZE)) + return CMOS_AREA_OVERLAPS_RTC; - if (config == CMOS_ENTRY_STRING) - return OK; + if (config == CMOS_ENTRY_STRING) + return OK; - if (length > (8 * sizeof(unsigned long long))) - return CMOS_AREA_TOO_WIDE; + if (length > (8 * sizeof(unsigned long long))) + return CMOS_AREA_TOO_WIDE; - return OK; - } + return OK; +} /**************************************************************************** * cmos_bit_op_strategy @@ -290,15 +296,16 @@ int verify_cmos_op (unsigned bit, unsigned length, cmos_entry_config_t config) * Helper function used by cmos_read() and cmos_write() to determine which * bits to read or write next. ****************************************************************************/ -static unsigned cmos_bit_op_strategy (unsigned bit, unsigned bits_left, - cmos_bit_op_location_t *where) - { unsigned max_bits; +static unsigned cmos_bit_op_strategy(unsigned bit, unsigned bits_left, + cmos_bit_op_location_t * where) +{ + unsigned max_bits; - where->byte_index = bit >> 3; - where->bit_offset = bit & 0x07; - max_bits = 8 - where->bit_offset; - return (bits_left > max_bits) ? max_bits : bits_left; - } + where->byte_index = bit >> 3; + where->bit_offset = bit & 0x07; + max_bits = 8 - where->bit_offset; + return (bits_left > max_bits) ? max_bits : bits_left; +} /**************************************************************************** * cmos_read_bits @@ -306,11 +313,12 @@ static unsigned cmos_bit_op_strategy (unsigned bit, unsigned bits_left, * Read a chunk of bits from a byte location within CMOS memory. Return the * value represented by the chunk of bits. ****************************************************************************/ -static unsigned char cmos_read_bits (const cmos_bit_op_location_t *where, - unsigned nr_bits) - { return (cmos_read_byte(where->byte_index) >> where->bit_offset) & - ((unsigned char) ((1 << nr_bits) - 1)); - } +static unsigned char cmos_read_bits(const cmos_bit_op_location_t * where, + unsigned nr_bits) +{ + return (cmos_read_byte(where->byte_index) >> where->bit_offset) & + ((unsigned char)((1 << nr_bits) - 1)); +} /**************************************************************************** * cmos_write_bits @@ -318,17 +326,18 @@ static unsigned char cmos_read_bits (const cmos_bit_op_location_t *where, * Write a chunk of bits (the low order 'nr_bits' bits of 'value') to an area * within a particular byte of CMOS memory. ****************************************************************************/ -static void cmos_write_bits (const cmos_bit_op_location_t *where, - unsigned nr_bits, unsigned char value) - { unsigned char n, mask; - - if (nr_bits == 8) - { cmos_write_byte(where->byte_index, value); - return; - } - - n = cmos_read_byte(where->byte_index); - mask = ((unsigned char) ((1 << nr_bits) - 1)) << where->bit_offset; - n = (n & ~mask) + ((value << where->bit_offset) & mask); - cmos_write_byte(where->byte_index, n); - } +static void cmos_write_bits(const cmos_bit_op_location_t * where, + unsigned nr_bits, unsigned char value) +{ + unsigned char n, mask; + + if (nr_bits == 8) { + cmos_write_byte(where->byte_index, value); + return; + } + + n = cmos_read_byte(where->byte_index); + mask = ((unsigned char)((1 << nr_bits) - 1)) << where->bit_offset; + n = (n & ~mask) + ((value << where->bit_offset) & mask); + cmos_write_byte(where->byte_index, n); +}