1 /*****************************************************************************\
4 *****************************************************************************
5 * Copyright (C) 2002-2005 The Regents of the University of California.
6 * Produced at the Lawrence Livermore National Laboratory.
7 * Written by David S. Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>.
11 * This file is part of nvramtool, a utility for reading/writing coreboot
12 * parameters and displaying information from the coreboot table.
13 * For details, see http://coreboot.org/nvramtool.
15 * Please also read the file DISCLAIMER which is included in this software
18 * This program is free software; you can redistribute it and/or modify it
19 * under the terms of the GNU General Public License (as published by the
20 * Free Software Foundation) version 2, dated June 1991.
22 * This program is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
25 * conditions of the GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License along
28 * with this program; if not, write to the Free Software Foundation, Inc.,
29 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
30 \*****************************************************************************/
34 #include "cmos_lowlevel.h"
36 static int prepare_cmos_op_common (const cmos_entry_t *e);
38 /****************************************************************************
39 * prepare_cmos_op_common
41 * Perform a few checks common to both reads and writes.
42 ****************************************************************************/
43 static int prepare_cmos_op_common (const cmos_entry_t *e)
46 if (e->config == CMOS_ENTRY_RESERVED)
47 /* Access to reserved parameters is not permitted. */
48 return CMOS_OP_RESERVED;
50 if ((result = verify_cmos_op(e->bit, e->length)) != OK)
53 assert(e->length > 0);
57 /****************************************************************************
60 * The caller wishes to read a CMOS parameter represented by 'e'. Perform
61 * sanity checking on 'e'. If a problem was found with e, return an error
62 * code. Else return OK.
63 ****************************************************************************/
64 int prepare_cmos_read (const cmos_entry_t *e)
67 if ((result = prepare_cmos_op_common(e)) != OK)
71 { case CMOS_ENTRY_ENUM:
82 /****************************************************************************
85 * The caller wishes to set a CMOS parameter represented by 'e' to a value
86 * whose string representation is stored in 'value_str'. Perform sanity
87 * checking on 'value_str'. On error, return an error code. Else store the
88 * numeric equivalent of 'value_str' in '*value' and return OK.
89 ****************************************************************************/
90 int prepare_cmos_write (const cmos_entry_t *e, const char value_str[],
91 unsigned long long *value)
92 { const cmos_enum_t *q;
93 unsigned long long out;
95 int negative, result, found_one;
97 if ((result = prepare_cmos_op_common(e)) != OK)
101 { case CMOS_ENTRY_ENUM:
102 /* Make sure the user's input corresponds to a valid option. */
103 for (q = first_cmos_enum_id(e->config_id), found_one = 0;
105 q = next_cmos_enum_id(q))
108 if (!strncmp(q->text, value_str, CMOS_MAX_TEXT_LENGTH))
113 return CMOS_OP_NO_MATCHING_ENUM;
116 return CMOS_OP_BAD_ENUM_VALUE;
122 /* See if the first character of 'value_str' (excluding any initial
123 * whitespace) is a minus sign.
125 for (p = value_str; isspace(*p); p++);
126 negative = (*p == '-');
128 out = strtoull(value_str, (char **) &p, 0);
131 return CMOS_OP_INVALID_INT;
133 /* If we get this far, the user specified a valid integer. However
134 * we do not currently support the use of negative numbers as CMOS
138 return CMOS_OP_NEGATIVE_INT;
146 if ((e->length < (8 * sizeof(*value))) &&
147 (out >= (1ull << e->length)))
148 return CMOS_OP_VALUE_TOO_WIDE;
154 /****************************************************************************
157 * Read the checksum for the coreboot parameters stored in CMOS and return
159 ****************************************************************************/
160 uint16_t cmos_checksum_read (void)
163 /* The checksum is stored in a big-endian format. */
164 hi = cmos_read_byte(cmos_checksum_index);
165 lo = cmos_read_byte(cmos_checksum_index + 1);
166 return (hi << 8) + lo;
169 /****************************************************************************
170 * cmos_checksum_write
172 * Set the checksum for the coreboot parameters stored in CMOS to
174 ****************************************************************************/
175 void cmos_checksum_write (uint16_t checksum)
176 { unsigned char lo, hi;
178 /* The checksum is stored in a big-endian format. */
179 hi = (unsigned char) (checksum >> 8);
180 lo = (unsigned char) (checksum & 0x00ff);
181 cmos_write_byte(cmos_checksum_index, hi);
182 cmos_write_byte(cmos_checksum_index + 1, lo);
185 /****************************************************************************
186 * cmos_checksum_compute
188 * Compute a checksum for the coreboot parameter values currently stored in
189 * CMOS and return this checksum.
190 ****************************************************************************/
191 uint16_t cmos_checksum_compute (void)
196 for (i = cmos_checksum_start; i <= cmos_checksum_end; i++)
197 sum += cmos_read_byte(i);
199 return ~((uint16_t) (sum & 0xffff));
202 /****************************************************************************
203 * cmos_checksum_verify
205 * Verify that the coreboot CMOS checksum is valid. If checksum is not
206 * valid then print warning message and exit.
207 ****************************************************************************/
208 void cmos_checksum_verify (void)
209 { uint16_t computed, actual;
212 computed = cmos_checksum_compute();
213 actual = cmos_checksum_read();
216 if (computed != actual)
217 { fprintf(stderr, "%s: Warning: Coreboot CMOS checksum is bad.\n",