[coreboot-gerrit] New patch to review for coreboot: 58b0a94 mc146818: Determine checksum position at runtime.
Vladimir Serbinenko (phcoder@gmail.com)
gerrit at coreboot.org
Mon Jan 27 01:54:36 CET 2014
Vladimir Serbinenko (phcoder at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/4831
-gerrit
commit 58b0a94d1d42b091f09eb8772fffb59bc0f2ec8b
Author: Vladimir Serbinenko <phcoder at gmail.com>
Date: Mon Jan 27 00:32:50 2014 +0100
mc146818: Determine checksum position at runtime.
Change-Id: I984427545754673c5f2191fb2a40c656ea1c379a
Signed-off-by: Vladimir Serbinenko <phcoder at gmail.com>
---
src/drivers/pc80/mc146818rtc.c | 77 ++++++++++++++++++++--------
src/drivers/pc80/mc146818rtc_early.c | 97 ++++++++++++++++++++++++------------
2 files changed, 123 insertions(+), 51 deletions(-)
diff --git a/src/drivers/pc80/mc146818rtc.c b/src/drivers/pc80/mc146818rtc.c
index 51cd6c3..0f44444 100644
--- a/src/drivers/pc80/mc146818rtc.c
+++ b/src/drivers/pc80/mc146818rtc.c
@@ -5,7 +5,6 @@
#include <boot/coreboot_tables.h>
#include <string.h>
#if CONFIG_USE_OPTION_TABLE
-#include "option_table.h"
#include <cbfs.h>
#endif
#if CONFIG_HAVE_ACPI_RESUME
@@ -27,28 +26,69 @@ static void rtc_update_cmos_date(u8 has_century)
}
#if CONFIG_USE_OPTION_TABLE
-static int rtc_checksum_valid(int range_start, int range_end, int cks_loc)
+static struct cmos_checksum *get_cmos_checksum_range(void)
+{
+ struct cmos_option_table *ct;
+ struct cmos_checksum *cc;
+
+ ct = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "cmos_layout.bin",
+ CBFS_COMPONENT_CMOS_LAYOUT, NULL);
+ if (!ct)
+ return 0;
+ cc=(struct cmos_checksum*)((unsigned char *)ct + ct->header_length);
+ for(;cc->tag==LB_TAG_OPTION || cc->tag==LB_TAG_OPTION_ENUM
+ || cc->tag == LB_TAG_OPTION_DEFAULTS;
+ cc=(struct cmos_checksum*)((unsigned char *)cc + cc->size));
+ if (cc->tag != LB_TAG_OPTION_CHECKSUM)
+ return 0;
+ return cc;
+}
+
+static int overlaps_checksum(u8 byte)
+{
+ struct cmos_checksum *cc;
+
+ cc = get_cmos_checksum_range();
+ if (!cc)
+ return 0;
+
+ return (cc->range_start <= byte) && (byte <= cc->range_end);
+}
+
+static int rtc_checksum_valid(void)
{
int i;
u16 sum, old_sum;
+ struct cmos_checksum *cc;
+
+ cc = get_cmos_checksum_range();
+ if (!cc)
+ return 0;
+
sum = 0;
- for(i = range_start; i <= range_end; i++) {
+ for(i = cc->range_start; i <= cc->range_end; i++) {
sum += cmos_read(i);
}
- old_sum = ((cmos_read(cks_loc)<<8) | cmos_read(cks_loc+1))&0x0ffff;
+ old_sum = ((cmos_read(cc->location)<<8) | cmos_read(cc->location+1))&0x0ffff;
return sum == old_sum;
}
-static void rtc_set_checksum(int range_start, int range_end, int cks_loc)
+static void rtc_set_checksum(void)
{
int i;
u16 sum;
+ struct cmos_checksum *cc;
+
+ cc = get_cmos_checksum_range();
+ if (!cc)
+ return;
+
sum = 0;
- for(i = range_start; i <= range_end; i++) {
+ for(i = cc->range_start; i <= cc->range_end; i++) {
sum += cmos_read(i);
}
- cmos_write(((sum >> 8) & 0x0ff), cks_loc);
- cmos_write(((sum >> 0) & 0x0ff), cks_loc+1);
+ cmos_write(((sum >> 8) & 0x0ff), cc->location);
+ cmos_write(((sum >> 0) & 0x0ff), cc->location+1);
}
#endif
@@ -90,8 +130,7 @@ void rtc_init(int invalid)
cmos_invalid = !(x & RTC_VRT);
/* See if there is a CMOS checksum error */
- checksum_invalid = !rtc_checksum_valid(PC_CKS_RANGE_START,
- PC_CKS_RANGE_END,PC_CKS_LOC);
+ checksum_invalid = !rtc_checksum_valid();
#define CLEAR_CMOS 0
#else
@@ -129,14 +168,12 @@ void rtc_init(int invalid)
#if CONFIG_USE_OPTION_TABLE
/* See if there is a LB CMOS checksum error */
- checksum_invalid = !rtc_checksum_valid(LB_CKS_RANGE_START,
- LB_CKS_RANGE_END,LB_CKS_LOC);
+ checksum_invalid = !rtc_checksum_valid();
if(checksum_invalid)
printk(BIOS_DEBUG, "RTC: coreboot checksum invalid\n");
/* Make certain we have a valid checksum */
- rtc_set_checksum(PC_CKS_RANGE_START,
- PC_CKS_RANGE_END,PC_CKS_LOC);
+ rtc_set_checksum();
#endif
/* Clear any pending interrupts */
@@ -214,7 +251,7 @@ enum cb_err get_option(void *dest, const char *name)
if(get_cmos_value(ce->bit, ce->length, dest) != CB_SUCCESS)
return CB_CMOS_ACCESS_ERROR;
- if(!rtc_checksum_valid(LB_CKS_RANGE_START, LB_CKS_RANGE_END,LB_CKS_LOC))
+ if(!rtc_checksum_valid())
return CB_CMOS_CHECKSUM_INVALID;
return CB_SUCCESS;
}
@@ -239,21 +276,21 @@ static enum cb_err set_cmos_value(unsigned long bit, unsigned long length,
uchar &= ~mask;
uchar |= (ret[0] << byte_bit);
cmos_write(uchar, byte);
- if (byte >= LB_CKS_RANGE_START && byte <= LB_CKS_RANGE_END)
+ if (overlaps_checksum (byte))
chksum_update_needed = 1;
} else { /* more that one byte so transfer the whole bytes */
if (byte_bit || length % 8)
return CB_ERR_ARG;
- for(i=0; length; i++, length-=8, byte++)
+ for(i=0; length; i++, length-=8, byte++) {
cmos_write(ret[i], byte);
- if (byte >= LB_CKS_RANGE_START && byte <= LB_CKS_RANGE_END)
+ if (overlaps_checksum (byte))
chksum_update_needed = 1;
+ }
}
if (chksum_update_needed) {
- rtc_set_checksum(LB_CKS_RANGE_START,
- LB_CKS_RANGE_END,LB_CKS_LOC);
+ rtc_set_checksum();
}
return CB_SUCCESS;
}
diff --git a/src/drivers/pc80/mc146818rtc_early.c b/src/drivers/pc80/mc146818rtc_early.c
index bb6caf1..3bf7e82 100644
--- a/src/drivers/pc80/mc146818rtc_early.c
+++ b/src/drivers/pc80/mc146818rtc_early.c
@@ -8,10 +8,6 @@
#endif
#include <boot/coreboot_tables.h>
-#if CONFIG_USE_OPTION_TABLE
-#include "option_table.h"
-#endif
-
#ifndef CONFIG_MAX_REBOOT_CNT
#error "CONFIG_MAX_REBOOT_CNT not defined"
#endif
@@ -27,20 +23,75 @@ static int cmos_error(void)
return (reg_d & RTC_VRT) == 0;
}
+#ifdef __ROMCC__
+#define const_pointer uint32_t
+#else
+#define const_pointer const void *
+#endif
+
+#if CONFIG_USE_OPTION_TABLE
+static const_pointer find_first_entry(void)
+{
+ const struct cmos_option_table *ct;
+#ifdef __ROMCC__
+ ct = walkcbfs("cmos_layout.bin");
+#else
+ ct = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "cmos_layout.bin",
+ CBFS_COMPONENT_CMOS_LAYOUT, NULL);
+#endif
+ if (!ct)
+ return 0;
+ return (const_pointer) ((const unsigned char *) ct + ct->header_length);
+}
+
+static const_pointer find_entry(const char *name)
+{
+ const struct cmos_entries *ce;
+
+ ce = (struct cmos_entries *) find_first_entry();
+ if (!ce)
+ return 0;
+ for(;ce->tag==LB_TAG_OPTION;
+ ce=(const struct cmos_entries*)((const unsigned char *)ce + ce->size)) {
+ unsigned i;
+ for (i = 0; ; i++) {
+ if (!(name[i] && i < CMOS_MAX_NAME_LENGTH))
+ return (const_pointer) ce;
+ if (name[i] != ce->name[i])
+ break;
+ }
+ }
+ return 0;
+}
+#endif
+
static int cmos_chksum_valid(void)
{
#if CONFIG_USE_OPTION_TABLE
unsigned char addr;
u16 sum, old_sum;
+ const struct cmos_checksum *cc;
+
+ cc = (struct cmos_checksum *) find_first_entry();
+
+ if (!cc)
+ return 0;
+
+ for(;cc->tag==LB_TAG_OPTION || cc->tag==LB_TAG_OPTION_ENUM
+ || cc->tag == LB_TAG_OPTION_DEFAULTS;
+ cc=(struct cmos_checksum*)((unsigned char *)cc + cc->size));
+ if (cc->tag != LB_TAG_OPTION_CHECKSUM)
+ return 0;
+
sum = 0;
/* Compute the cmos checksum */
- for(addr = LB_CKS_RANGE_START; addr <= LB_CKS_RANGE_END; addr++) {
+ for(addr = cc->range_start; addr <= cc->range_end; addr++) {
sum += cmos_read(addr);
}
/* Read the stored checksum */
- old_sum = cmos_read(LB_CKS_LOC) << 8;
- old_sum |= cmos_read(LB_CKS_LOC+1);
+ old_sum = cmos_read(cc->location) << 8;
+ old_sum |= cmos_read(cc->location+1);
return sum == old_sum;
#else
@@ -102,34 +153,18 @@ static inline int do_normal_boot(void)
unsigned read_option(const char *name, unsigned def)
{
#if CONFIG_USE_OPTION_TABLE
- struct cmos_option_table *ct;
- struct cmos_entries *ce;
+ const struct cmos_entries *ce;
+ unsigned byte;
-#ifdef __ROMCC__
- ct = (struct cmos_option_table *)walkcbfs("cmos_layout.bin");
-#else
- ct = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "cmos_layout.bin",
- CBFS_COMPONENT_CMOS_LAYOUT, NULL);
-#endif
+ ce = (struct cmos_entries *)find_entry(name);
- if (!ct)
+ if (!ce)
return def;
+
+ byte = cmos_read(ce->bit/8);
+ byte >>= (ce->bit & 7U);
- ce=(struct cmos_entries*)((unsigned char *)ct + ct->header_length);
- for(;ce->tag==LB_TAG_OPTION;
- ce=(struct cmos_entries*)((unsigned char *)ce + ce->size)) {
- unsigned byte;
- unsigned i;
- for (i = 0; name[i] && i < CMOS_MAX_NAME_LENGTH; i++)
- if (name[i] != ce->name[i])
- goto next_option;
- byte = cmos_read(ce->bit/8);
- byte >>= (ce->bit & 7U);
-
- return (byte) & ((1U << ce->length) - 1U);
- next_option:;
- }
- return def;
+ return (byte) & ((1U << ce->length) - 1U);
#else
return def;
#endif
More information about the coreboot-gerrit
mailing list