util/nvramtool: Remove "this file is part of" lines
[coreboot.git] / util / nvramtool / cmos_ops.c
blob6ba7505ff19d4b7cd093090159f832ce9cdb6675
1 /*****************************************************************************\
2 * cmos_ops.c
3 *****************************************************************************
4 * Please also read the file DISCLAIMER which is included in this software
5 * distribution.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License (as published by the
9 * Free Software Foundation) version 2, dated June 1991.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
14 * conditions of the GNU General Public License for more details.
15 \*****************************************************************************/
17 #include "common.h"
18 #include "cmos_ops.h"
19 #include "cmos_lowlevel.h"
21 static int prepare_cmos_op_common(const cmos_entry_t * e);
23 /****************************************************************************
24 * prepare_cmos_op_common
26 * Perform a few checks common to both reads and writes.
27 ****************************************************************************/
28 static int prepare_cmos_op_common(const cmos_entry_t * e)
30 int result;
32 if (e->config == CMOS_ENTRY_RESERVED)
33 /* Access to reserved parameters is not permitted. */
34 return CMOS_OP_RESERVED;
36 if ((result = verify_cmos_op(e->bit, e->length, e->config)) != OK)
37 return result;
39 assert(e->length > 0);
40 return OK;
43 /****************************************************************************
44 * prepare_cmos_read
46 * The caller wishes to read a CMOS parameter represented by 'e'. Perform
47 * sanity checking on 'e'. If a problem was found with e, return an error
48 * code. Else return OK.
49 ****************************************************************************/
50 int prepare_cmos_read(const cmos_entry_t * e)
52 int result;
54 if ((result = prepare_cmos_op_common(e)) != OK)
55 return result;
57 switch (e->config) {
58 case CMOS_ENTRY_ENUM:
59 case CMOS_ENTRY_HEX:
60 case CMOS_ENTRY_STRING:
61 break;
63 default:
64 BUG();
67 return OK;
70 /****************************************************************************
71 * prepare_cmos_write
73 * The caller wishes to set a CMOS parameter represented by 'e' to a value
74 * whose string representation is stored in 'value_str'. Perform sanity
75 * checking on 'value_str'. On error, return an error code. Else store the
76 * numeric equivalent of 'value_str' in '*value' and return OK.
77 ****************************************************************************/
78 int prepare_cmos_write(const cmos_entry_t * e, const char value_str[],
79 unsigned long long *value)
81 const cmos_enum_t *q;
82 unsigned long long out;
83 const char *p;
84 char *memory = NULL;
85 int negative, result, found_one;
87 if ((result = prepare_cmos_op_common(e)) != OK)
88 return result;
90 switch (e->config) {
91 case CMOS_ENTRY_ENUM:
92 /* Make sure the user's input corresponds to a valid option. */
93 for (q = first_cmos_enum_id(e->config_id), found_one = 0;
94 q != NULL; q = next_cmos_enum_id(q)) {
95 found_one = 1;
97 if (!strncmp(q->text, value_str, CMOS_MAX_TEXT_LENGTH))
98 break;
101 if (!found_one)
102 return CMOS_OP_NO_MATCHING_ENUM;
104 if (q == NULL)
105 return CMOS_OP_BAD_ENUM_VALUE;
107 out = q->value;
108 break;
110 case CMOS_ENTRY_HEX:
111 /* See if the first character of 'value_str' (excluding
112 * any initial whitespace) is a minus sign.
114 for (p = value_str; isspace((int)(unsigned char)*p); p++) ;
115 negative = (*p == '-');
117 out = strtoull(value_str, (char **)&p, 0);
119 if (*p)
120 return CMOS_OP_INVALID_INT;
122 /* If we get this far, the user specified a valid integer.
123 * However we do not currently support the use of negative
124 * numbers as CMOS parameter values.
126 if (negative)
127 return CMOS_OP_NEGATIVE_INT;
129 break;
131 case CMOS_ENTRY_STRING:
132 if (e->length < (8 * strlen(value_str)))
133 return CMOS_OP_VALUE_TOO_WIDE;
134 memory = malloc(e->length / 8);
135 memset(memory, 0, e->length / 8);
136 strcpy(memory, value_str);
137 out = (unsigned long)memory;
138 break;
140 default:
141 BUG();
144 if ((e->length < (8 * sizeof(*value))) && (out >= (1ull << e->length))) {
145 if (memory) free(memory);
146 return CMOS_OP_VALUE_TOO_WIDE;
149 *value = out;
150 return OK;
153 /****************************************************************************
154 * cmos_checksum_read
156 * Read the checksum for the coreboot parameters stored in CMOS and return
157 * this value.
158 ****************************************************************************/
159 uint16_t cmos_checksum_read(void)
161 uint16_t lo, hi;
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
173 * 'checksum'.
174 ****************************************************************************/
175 void cmos_checksum_write(uint16_t checksum)
177 unsigned char lo, hi;
179 /* The checksum is stored in a big-endian format. */
180 hi = (unsigned char)(checksum >> 8);
181 lo = (unsigned char)(checksum & 0x00ff);
182 cmos_write_byte(cmos_checksum_index, hi);
183 cmos_write_byte(cmos_checksum_index + 1, lo);
186 /****************************************************************************
187 * cmos_checksum_compute
189 * Compute a checksum for the coreboot parameter values currently stored in
190 * CMOS and return this checksum.
191 ****************************************************************************/
192 uint16_t cmos_checksum_compute(void)
194 unsigned i, sum;
196 sum = 0;
198 for (i = cmos_checksum_start; i <= cmos_checksum_end; i++)
199 sum += cmos_read_byte(i);
201 return (uint16_t)(sum & 0xffff);
204 /****************************************************************************
205 * cmos_checksum_verify
207 * Verify that the coreboot CMOS checksum is valid. If checksum is not
208 * valid then print warning message and exit.
209 ****************************************************************************/
210 void cmos_checksum_verify(void)
212 uint16_t computed, actual;
214 set_iopl(3);
215 computed = cmos_checksum_compute();
216 actual = cmos_checksum_read();
217 set_iopl(0);
219 if (computed != actual) {
220 fprintf(stderr, "%s: Warning: coreboot CMOS checksum is bad.\n",
221 prog_name);
222 fprintf(stderr, "Computed checksum: 0x%x. Stored checksum: 0x%x\n",
223 computed, actual);
224 exit(1);