Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/762
-gerrit
commit 93beab8640ca83f3d62731aecb9d4d56e201dc05
Author: Gabe Black <gabeblack(a)google.com>
Date: Sat Jan 7 01:03:42 2012 -0800
Revamp cbmem.py to use the coreboot tables.
This change makes significant changes to cbmem.py to make it use the
coreboot tables to find the memory console and timestamp areas instead
of looking for the in memory table TOC structure. That appears to be
more robust and gets cbmem.py working again after some unrelated
changes that affected memory layout.
It also introduces some small infrastructure to make accessing C style
structures in physical memory easier and more transparent.
Change-Id: I51833055a50c2d76423520ba6e059bf8fc50adea
Signed-off-by: Gabe Black <gabeblack(a)google.com>
---
util/cbmem/cbmem.py | 267 ++++++++++++++++++++++++++++++---------------------
1 files changed, 158 insertions(+), 109 deletions(-)
diff --git a/util/cbmem/cbmem.py b/util/cbmem/cbmem.py
index 3e8476d..f4f3e88 100755
--- a/util/cbmem/cbmem.py
+++ b/util/cbmem/cbmem.py
@@ -33,29 +33,46 @@ console sections.
'''
import mmap
-import re
import struct
import sys
-import time
-# These definitions follow src/include/cbmem.h
-CBMEM_MAGIC = 0x434f5245
-CBMEM_MAX_ENTRIES = 16
+def get_phys_mem(addr, size):
+ '''Read size bytes from address addr by mmaping /dev/mem'''
-CBMEM_ENTRY_FORMAT = '@LLQQ'
-CONSOLE_HEADER_FORMAT = '@LL'
-TIMESTAMP_HEADER_FORMAT = '@QLL'
-TIMESTAMP_ENTRY_FORMAT = '@LQ'
-
-mf_fileno = 0 # File number of the file providing access to memory.
-
-def align_up(base, alignment):
- '''Increment to the alignment boundary.
-
- Return the next integer larger than 'base' and divisible by 'alignment'.
- '''
-
- return base + alignment - base % alignment
+ mf = open("/dev/mem")
+ delta = addr % 4096
+ mm = mmap.mmap(mf.fileno(), size + delta,
+ mmap.MAP_PRIVATE, offset=(addr - delta))
+ buf = mm.read(size + delta)
+ mf.close()
+ return buf[delta:]
+
+# This class and metaclass make it easier to define and access structures
+# which live in physical memory. To use them, inherit from CStruct and define
+# a class member called struct_members which is a tuple of pairs. The first
+# item in the pair is the type format specifier that should be used with
+# struct.unpack to read that member from memory. The second item is the name
+# that member should have in the resulting object.
+
+class MetaCStruct(type):
+ def __init__(cls, name, bases, dct):
+ struct_members = dct["struct_members"]
+ cls.struct_fmt = "@"
+ for char, name in struct_members:
+ cls.struct_fmt += char
+ cls.struct_len = struct.calcsize(cls.struct_fmt)
+ super(MetaCStruct, cls).__init__(name, bases, dct)
+
+class CStruct(object):
+ __metaclass__ = MetaCStruct
+ struct_members = ()
+
+ def __init__(self, addr):
+ self.raw_memory = get_phys_mem(addr, self.struct_len)
+ values = struct.unpack(self.struct_fmt, self.raw_memory)
+ names = (name for char, name in self.struct_members)
+ for name, value in zip(names, values):
+ setattr(self, name, value)
def normalize_timer(value, freq):
'''Convert timer reading into microseconds.
@@ -96,109 +113,141 @@ def get_cpu_freq():
# Convert reading into Hertz
return float(freq_str) * 1000.0
-def get_mem_size():
- '''Retrieve amount of memory available to the CPU from /proc/meminfo.'''
- mult = {
- 'kB': 1024
- }
- meminfo = open('/proc/meminfo').read()
- m = re.search('MemTotal:.*\n', meminfo)
- mem_string = re.search('MemTotal:.*\n', meminfo).group(0)
- (_, size, mult_name) = mem_string.split()
- return int(size) * mult[mult_name]
-
-def parse_mem_at(addr, format):
- '''Read and parse a memory location.
-
- This function reads memory at the passed in address, parses it according
- to the passed in format specification and returns a list of values.
-
- The first value in the list is the size of data matching the format
- expression, and the rest of the elements of the list are the actual values
- retrieved using the format.
- '''
-
- size = struct.calcsize(format)
- delta = addr % 4096 # mmap requires the offset to be page size aligned.
- mm = mmap.mmap(mf_fileno, size + delta,
- mmap.MAP_PRIVATE, offset=(addr - delta))
- buf = mm.read(size + delta)
- mm.close()
- rv = [size,] + list(struct.unpack(format, buf[delta:size + delta + 1]))
- return rv
-
-def dprint(text):
- '''Debug print function.
-
- Edit it to get the debug output.
- '''
-
- if False:
- print text
-
def process_timers(base):
'''Scan the array of timestamps found in CBMEM at address base.
For each timestamp print the timer ID and the value in microseconds.
'''
- (step, base_time, max_entr, entr) = parse_mem_at(
- base, TIMESTAMP_HEADER_FORMAT)
-
- print('\ntime base %d, total entries %d' % (base_time, entr))
+ class TimestampHeader(CStruct):
+ struct_members = (
+ ("Q", "base_time"),
+ ("L", "max_entr"),
+ ("L", "entr")
+ )
+
+ class TimestampEntry(CStruct):
+ struct_members = (
+ ("L", "timer_id"),
+ ("Q", "timer_value")
+ )
+
+ header = TimestampHeader(base)
+ print('\ntime base %d, total entries %d' % (header.base_time, header.entr))
clock_freq = get_cpu_freq()
- base = base + step
- for i in range(entr):
- (step, timer_id, timer_value) = parse_mem_at(
- base, TIMESTAMP_ENTRY_FORMAT)
- print '%d:%s ' % (timer_id, normalize_timer(timer_value, clock_freq)),
- base = base + step
+ base = base + header.struct_len
+ for i in range(header.entr):
+ timestamp = TimestampEntry(base)
+ print '%d:%s ' % (timestamp.timer_id,
+ normalize_timer(timestamp.timer_value, clock_freq)),
+ base = base + timestamp.struct_len
print
def process_console(base):
'''Dump the console log buffer contents found at address base.'''
- (step, size, cursor) = parse_mem_at(base, CONSOLE_HEADER_FORMAT)
- print 'cursor at %d\n' % cursor
+ class ConsoleHeader(CStruct):
+ struct_members = (
+ ("L", "size"),
+ ("L", "cursor")
+ )
- cons_string_format = '%ds' % min(cursor, size)
- (_, cons_text) = parse_mem_at(base + step, cons_string_format)
+ header = ConsoleHeader(base)
+ print 'cursor at %d\n' % header.cursor
+
+ cons_addr = base + header.struct_len
+ cons_length = min(header.cursor, header.size)
+ cons_text = get_phys_mem(cons_addr, cons_length)
print cons_text
print '\n'
-mem_alignment = 1024 * 1024 * 1024 # 1 GBytes
-table_alignment = 128 * 1024
-
-mem_size = get_mem_size()
-
-# start at memory address aligned at 128K.
-offset = align_up(mem_size, table_alignment)
-
-dprint('mem_size %x offset %x' %(mem_size, offset))
-mf = open("/dev/mem")
-mf_fileno = mf.fileno()
-
-while offset % mem_alignment: # do not cross the 1G boundary while searching
- (step, magic, mid, base, size) = parse_mem_at(offset, CBMEM_ENTRY_FORMAT)
- if magic == CBMEM_MAGIC:
- offset = offset + step
- break
- offset += table_alignment
-else:
- print 'Did not find the CBMEM'
- sys.exit(0)
-
-for i in (range(1, CBMEM_MAX_ENTRIES)):
- (_, magic, mid, base, size) = parse_mem_at(offset, CBMEM_ENTRY_FORMAT)
- if mid == 0:
- break
-
- print '%x, %x, %x' % (mid, base, size)
- if mid == 0x54494d45:
- process_timers(base)
- if mid == 0x434f4e53:
- process_console(base)
-
- offset = offset + step
-
-mf.close()
+def ipchksum(buf):
+ '''Checksumming function used on the coreboot tables. The buffer being
+ checksummed is summed up as if it was an array of 16 bit unsigned
+ integers. If there are an odd number of bytes, the last element is zero
+ extended.'''
+
+ size = len(buf)
+ odd = size % 2
+ fmt = "<%dH" % ((size - odd) / 2)
+ if odd:
+ fmt += "B"
+ shorts = struct.unpack(fmt, buf)
+ checksum = sum(shorts)
+ checksum = (checksum >> 16) + (checksum & 0xffff)
+ checksum += (checksum >> 16)
+ checksum = ~checksum & 0xffff
+ return checksum
+
+def parse_tables(base, length):
+ '''Find the coreboot tables in memory and process whatever we can.'''
+
+ class CBTableHeader(CStruct):
+ struct_members = (
+ ("4s", "signature"),
+ ("I", "header_bytes"),
+ ("I", "header_checksum"),
+ ("I", "table_bytes"),
+ ("I", "table_checksum"),
+ ("I", "table_entries")
+ )
+
+ class CBTableEntry(CStruct):
+ struct_members = (
+ ("I", "tag"),
+ ("I", "size")
+ )
+
+ class CBTableForward(CBTableEntry):
+ struct_members = CBTableEntry.struct_members + (
+ ("Q", "forward"),
+ )
+
+ class CBMemTab(CBTableEntry):
+ struct_members = CBTableEntry.struct_members + (
+ ("L", "cbmem_tab"),
+ )
+
+ for addr in range(base, base + length, 16):
+ header = CBTableHeader(addr)
+ if header.signature == "LBIO":
+ break
+ else:
+ return -1
+
+ if header.header_bytes == 0:
+ return -1
+
+ if ipchksum(header.raw_memory) != 0:
+ print "Bad header checksum"
+ return -1
+
+ addr += header.header_bytes
+ table = get_phys_mem(addr, header.table_bytes)
+ if ipchksum(table) != header.table_checksum:
+ print "Bad table checksum"
+ return -1
+
+ for i in range(header.table_entries):
+ entry = CBTableEntry(addr)
+ if entry.tag == 0x11: # Forwarding entry
+ return parse_tables(CBTableForward(addr).forward, length)
+ elif entry.tag == 0x16: # Timestamps
+ process_timers(CBMemTab(addr).cbmem_tab)
+ elif entry.tag == 0x17: # CBMEM console
+ process_console(CBMemTab(addr).cbmem_tab)
+
+ addr += entry.size
+
+ return 0
+
+def main():
+ for base, length in (0x00000000, 0x1000), (0x000f0000, 0x1000):
+ if parse_tables(base, length):
+ break
+ else:
+ print "Didn't find the coreboot tables"
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main())
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/737
-gerrit
commit 0ad6291b03bec0e508421cf991864109fbbd5e97
Author: Stefan Reinauer <reinauer(a)chromium.org>
Date: Wed Oct 26 22:11:52 2011 +0000
add native memset() function on x86.
Change-Id: Ia118ebe0a4b59bdcefd78895141a365170f6aed2
Signed-off-by: Stefan Reinauer <reinauer(a)google.com>
---
src/arch/x86/Kconfig | 4 ++
src/arch/x86/lib/Makefile.inc | 2 +
src/arch/x86/lib/memset.c | 86 +++++++++++++++++++++++++++++++++++++++++
src/lib/Makefile.inc | 4 ++
4 files changed, 96 insertions(+), 0 deletions(-)
diff --git a/src/arch/x86/Kconfig b/src/arch/x86/Kconfig
index 74933af..078ae95 100644
--- a/src/arch/x86/Kconfig
+++ b/src/arch/x86/Kconfig
@@ -80,6 +80,10 @@ config CMOS_DEFAULT_FILE
config BOOTBLOCK_SOUTHBRIDGE_INIT
string
+config HAVE_ARCH_MEMSET
+ bool
+ default y
+
config HAVE_ARCH_MEMCPY
bool
default y
diff --git a/src/arch/x86/lib/Makefile.inc b/src/arch/x86/lib/Makefile.inc
index f99e429..3f4dc95 100644
--- a/src/arch/x86/lib/Makefile.inc
+++ b/src/arch/x86/lib/Makefile.inc
@@ -8,10 +8,12 @@ ramstage-$(CONFIG_MMCONF_SUPPORT) += pci_ops_mmconf.c
ramstage-y += pci_ops_auto.c
ramstage-y += exception.c
ramstage-$(CONFIG_IOAPIC) += ioapic.c
+ramstage-y += memset.c
ramstage-y += memcpy.c
romstage-y += romstage_console.c
romstage-y += cbfs_and_run.c
+romstage-y += memset.c
romstage-y += memcpy.c
smm-y += memcpy.c
diff --git a/src/arch/x86/lib/memset.c b/src/arch/x86/lib/memset.c
new file mode 100644
index 0000000..e850726
--- /dev/null
+++ b/src/arch/x86/lib/memset.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 1991,1992,1993,1997,1998,2003, 2005 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* From glibc-2.14, sysdeps/i386/memset.c */
+
+#include <string.h>
+#include <stdint.h>
+
+typedef uint32_t op_t;
+
+void *memset(void *dstpp, int c, size_t len)
+{
+ int d0;
+ unsigned long int dstp = (unsigned long int) dstpp;
+
+ /* This explicit register allocation improves code very much indeed. */
+ register op_t x asm("ax");
+
+ x = (unsigned char) c;
+
+ /* Clear the direction flag, so filling will move forward. */
+ asm volatile("cld");
+
+ /* This threshold value is optimal. */
+ if (len >= 12) {
+ /* Fill X with four copies of the char we want to fill with. */
+ x |= (x << 8);
+ x |= (x << 16);
+
+ /* Adjust LEN for the bytes handled in the first loop. */
+ len -= (-dstp) % sizeof(op_t);
+
+ /*
+ * There are at least some bytes to set. No need to test for
+ * LEN == 0 in this alignment loop.
+ */
+
+ /* Fill bytes until DSTP is aligned on a longword boundary. */
+ asm volatile(
+ "rep\n"
+ "stosb" /* %0, %2, %3 */ :
+ "=D" (dstp), "=c" (d0) :
+ "0" (dstp), "1" ((-dstp) % sizeof(op_t)), "a" (x) :
+ "memory");
+
+ /* Fill longwords. */
+ asm volatile(
+ "rep\n"
+ "stosl" /* %0, %2, %3 */ :
+ "=D" (dstp), "=c" (d0) :
+ "0" (dstp), "1" (len / sizeof(op_t)), "a" (x) :
+ "memory");
+ len %= sizeof(op_t);
+ }
+
+ /* Write the last few bytes. */
+ asm volatile(
+ "rep\n"
+ "stosb" /* %0, %2, %3 */ :
+ "=D" (dstp), "=c" (d0) :
+ "0" (dstp), "1" (len), "a" (x) :
+ "memory");
+
+ return dstpp;
+}
diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc
index 61b6451..8ce72b2 100644
--- a/src/lib/Makefile.inc
+++ b/src/lib/Makefile.inc
@@ -1,6 +1,8 @@
+ifneq ($(CONFIG_HAVE_ARCH_MEMSET),y)
romstage-y += memset.c
+endif
romstage-y += memchr.c
ifneq ($(CONFIG_HAVE_ARCH_MEMCPY),y)
romstage-y += memcpy.c
@@ -19,7 +21,9 @@ romstage-$(CONFIG_CONSOLE_NE2K) += compute_ip_checksum.c
romstage-$(CONFIG_USBDEBUG) += usbdebug.c
romstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c
+ifneq ($(CONFIG_HAVE_ARCH_MEMSET),y)
ramstage-y += memset.c
+endif
ramstage-y += memchr.c
ifneq ($(CONFIG_HAVE_ARCH_MEMCPY),y)
ramstage-y += memcpy.c
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/750
-gerrit
commit 7beb072eab7678c45319fd52e5c7d5372342d24b
Author: Vadim Bendebury <vbendeb(a)chromium.org>
Date: Sat Nov 5 02:07:01 2011 +0000
Fix coreboot makefiles not to produce half baked output.
It looks like the cbfstool utility generates the output file even when
it fails to generate it properly. This causes make, if started second
time in a row, after cbfstool failure, to continue beyond the point of
failure (as the corrupted output file is present in the output tree,
the second make invocation presumes that it is valid, as it is newer
than the dependencies).
The output file should be created only when successful, in an atomic
operation. There could be other places in the make system which
require a similar fix, this needs to be investigated further.
Change-Id: I7c17f033ee5937eb712b1a594122430cee5c9146
Signed-off-by: Vadim Bendebury <vbendeb(a)chromium.org>
---
src/arch/x86/Makefile.inc | 16 +++++++++-------
1 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc
index aeb4875..b2b9143 100755
--- a/src/arch/x86/Makefile.inc
+++ b/src/arch/x86/Makefile.inc
@@ -58,13 +58,15 @@ extract_nth=$(word $(1), $(subst |, ,$(2)))
ifneq ($(CONFIG_UPDATE_IMAGE),y)
prebuild-files = \
$(foreach file,$(cbfs-files), \
- $(CBFSTOOL) $@ add $(call extract_nth,1,$(file)) $(call extract_nth,2,$(file)) $(call extract_nth,3,$(file)) $(call extract_nth,4,$(file)); )
+ $(CBFSTOOL) $@.tmp add $(call extract_nth,1,$(file)) \
+ $(call extract_nth,2,$(file)) $(call extract_nth,3,$(file)) \
+ $(call extract_nth,4,$(file)) &&)
prebuilt-files = $(foreach file,$(cbfs-files), $(call extract_nth,1,$(file)))
$(obj)/coreboot.pre1: $(obj)/coreboot.bootblock $$(prebuilt-files) $(CBFSTOOL)
- rm -f $@
- $(CBFSTOOL) $@ create $(CONFIG_COREBOOT_ROMSIZE_KB)K $(obj)/coreboot.bootblock
- $(prebuild-files)
+ $(CBFSTOOL) $@.tmp create $(CONFIG_COREBOOT_ROMSIZE_KB)K $(obj)/coreboot.bootblock
+ $(prebuild-files) true
+ mv $@.tmp $@
else
.PHONY: $(obj)/coreboot.pre1
$(obj)/coreboot.pre1: $(CBFSTOOL)
@@ -269,10 +271,10 @@ endif
$(obj)/coreboot.pre: $(obj)/coreboot.romstage $(obj)/coreboot.pre1 $(CBFSTOOL)
@printf " CBFS $(subst $(obj)/,,$(@))\n"
- rm -f $@
- cp $(obj)/coreboot.pre1 $@
- $(CBFSTOOL) $@ add-stage $(obj)/romstage.elf \
+ cp $(obj)/coreboot.pre1 $@.tmp
+ $(CBFSTOOL) $@.tmp add-stage $(obj)/romstage.elf \
$(CONFIG_CBFS_PREFIX)/romstage x 0x$(shell cat $(obj)/location.txt)
+ mv $@.tmp $@
#FIXME: location.txt might require an offset of header size
#######################################################################
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/751
-gerrit
commit 3bbcbe8d46d047f2ff2dc5b7ee1d156a25be08b5
Author: Vadim Bendebury <vbendeb(a)chromium.org>
Date: Wed Nov 9 14:11:26 2011 -0800
Allow components smaller than declared size.
idftool was failing to add the ME blobs into the output image in case
the blob size does not exactly match the size allocated for it in the
flashrom structure.
It is difficult to set the field in the structure to exactly match the
size (for some reason Intel flash tool fails to insert the correct
size even when given the exact ME blob). On the other hand there is no
harm in using am ME blob smaller than the allocated size, this change
modifies the tool building the image to allow for smaller components.
Change-Id: I1b04f90051b91157391943c9bad0eb06dd297431
Signed-off-by: Vadim Bendebury <vbendeb(a)chromium.org>
---
util/ifdtool/ifdtool.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/util/ifdtool/ifdtool.c b/util/ifdtool/ifdtool.c
index eb91b2c..8c1077c 100644
--- a/util/ifdtool/ifdtool.c
+++ b/util/ifdtool/ifdtool.c
@@ -334,7 +334,7 @@ void inject_region(char *filename, char *image, int size, int region_type,
printf("File %s is %d bytes\n", region_fname, region_size);
if ( (region_size > region.size) || ((region_type != 1) &&
- (region_size != region.size))) {
+ (region_size > region.size))) {
fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x)"
" bytes. Not injecting.\n",
region_name(region_type), region.size,