[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