1 /*****************************************************************************\
3 *****************************************************************************
4 * Copyright (C) 2002-2005 The Regents of the University of California.
5 * Produced at the Lawrence Livermore National Laboratory.
6 * Written by David S. Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>.
10 * This file is part of nvramtool, a utility for reading/writing coreboot
11 * parameters and displaying information from the coreboot table.
12 * For details, see http://coreboot.org/nvramtool.
14 * Please also read the file DISCLAIMER which is included in this software
17 * This program is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License (as published by the
19 * Free Software Foundation) version 2, dated June 1991.
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
24 * conditions of the GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
29 \*****************************************************************************/
33 #include "cmos_lowlevel.h"
35 static int prepare_cmos_op_common (const cmos_entry_t *e);
37 /****************************************************************************
38 * prepare_cmos_op_common
40 * Perform a few checks common to both reads and writes.
41 ****************************************************************************/
42 static int prepare_cmos_op_common (const cmos_entry_t *e)
45 if (e->config == CMOS_ENTRY_RESERVED)
46 /* Access to reserved parameters is not permitted. */
47 return CMOS_OP_RESERVED;
49 if ((result = verify_cmos_op(e->bit, e->length, e->config)) != OK)
52 assert(e->length > 0);
56 /****************************************************************************
59 * The caller wishes to read a CMOS parameter represented by 'e'. Perform
60 * sanity checking on 'e'. If a problem was found with e, return an error
61 * code. Else return OK.
62 ****************************************************************************/
63 int prepare_cmos_read (const cmos_entry_t *e)
66 if ((result = prepare_cmos_op_common(e)) != OK)
70 { case CMOS_ENTRY_ENUM:
72 case CMOS_ENTRY_STRING:
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;
96 int negative, result, found_one;
98 if ((result = prepare_cmos_op_common(e)) != OK)
102 { case CMOS_ENTRY_ENUM:
103 /* Make sure the user's input corresponds to a valid option. */
104 for (q = first_cmos_enum_id(e->config_id), found_one = 0;
106 q = next_cmos_enum_id(q))
109 if (!strncmp(q->text, value_str, CMOS_MAX_TEXT_LENGTH))
114 return CMOS_OP_NO_MATCHING_ENUM;
117 return CMOS_OP_BAD_ENUM_VALUE;
123 /* See if the first character of 'value_str' (excluding any initial
124 * whitespace) is a minus sign.
126 for (p = value_str; isspace(*p); p++);
127 negative = (*p == '-');
129 out = strtoull(value_str, (char **) &p, 0);
132 return CMOS_OP_INVALID_INT;
134 /* If we get this far, the user specified a valid integer. However
135 * we do not currently support the use of negative numbers as CMOS
139 return CMOS_OP_NEGATIVE_INT;
143 case CMOS_ENTRY_STRING:
144 if (e->length < (8 * strlen(value_str)))
145 return CMOS_OP_VALUE_TOO_WIDE;
146 memory = malloc(e->length / 8);
147 memset(memory, 0, e->length / 8);
148 strcpy(memory, value_str);
149 out = (unsigned long)memory;
156 if ((e->length < (8 * sizeof(*value))) &&
157 (out >= (1ull << e->length)))
158 return CMOS_OP_VALUE_TOO_WIDE;
164 /****************************************************************************
167 * Read the checksum for the coreboot parameters stored in CMOS and return
169 ****************************************************************************/
170 uint16_t cmos_checksum_read (void)
173 /* The checksum is stored in a big-endian format. */
174 hi = cmos_read_byte(cmos_checksum_index);
175 lo = cmos_read_byte(cmos_checksum_index + 1);
176 return (hi << 8) + lo;
179 /****************************************************************************
180 * cmos_checksum_write
182 * Set the checksum for the coreboot parameters stored in CMOS to
184 ****************************************************************************/
185 void cmos_checksum_write (uint16_t checksum)
186 { unsigned char lo, hi;
188 /* The checksum is stored in a big-endian format. */
189 hi = (unsigned char) (checksum >> 8);
190 lo = (unsigned char) (checksum & 0x00ff);
191 cmos_write_byte(cmos_checksum_index, hi);
192 cmos_write_byte(cmos_checksum_index + 1, lo);
195 /****************************************************************************
196 * cmos_checksum_compute
198 * Compute a checksum for the coreboot parameter values currently stored in
199 * CMOS and return this checksum.
200 ****************************************************************************/
201 uint16_t cmos_checksum_compute (void)
206 for (i = cmos_checksum_start; i <= cmos_checksum_end; i++)
207 sum += cmos_read_byte(i);
209 return ~((uint16_t) (sum & 0xffff));
212 /****************************************************************************
213 * cmos_checksum_verify
215 * Verify that the coreboot CMOS checksum is valid. If checksum is not
216 * valid then print warning message and exit.
217 ****************************************************************************/
218 void cmos_checksum_verify (void)
219 { uint16_t computed, actual;
222 computed = cmos_checksum_compute();
223 actual = cmos_checksum_read();
226 if (computed != actual)
227 { fprintf(stderr, "%s: Warning: Coreboot CMOS checksum is bad.\n",