coreboot-kgpe-d16/util/nvramtool/cmos_ops.c
Stefan Reinauer 14e2277962 Since some people disapprove of white space cleanups mixed in regular commits
while others dislike them being extra commits, let's clean them up once and
for all for the existing code. If it's ugly, let it only be ugly once :-)

Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Acked-by: Stefan Reinauer <stepan@coresystems.de>



git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5507 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
2010-04-27 06:56:47 +00:00

236 lines
6.9 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.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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);
}
}