[SeaBIOS] [PATCH 2/2] accept MADT over fw_cfg
Michael S. Tsirkin
mst at redhat.com
Tue Apr 23 17:22:12 CEST 2013
On Mon, Apr 22, 2013 at 08:42:18PM -0400, Kevin O'Connor wrote:
> On Mon, Apr 22, 2013 at 08:23:39PM +0300, Michael S. Tsirkin wrote:
> > > @@ -0,0 +1,28 @@
> > > +#include "types.h" // u8
> > > +#include "util.h" // romfile_s
> > > +
> > > +/* ROM file linker interface. Linker uses little endian format */
> > > +struct linker_entry_s {
> > > + u8 size; /* size in bytes including the header */
> > > + u8 bytes; /* How many bytes to change. Can be 1,2,4 or 8. */
> > > + u8 type;
> > > + u8 format;
> > > + u32 reserved;
> > > + u64 src_offset; /* Offset in source. Little endian format. */
> >
> > src_offset is not needed: host can pre-fill destination
> > table with the offset value.
> > Will probably drop it.
> >
> > > + u64 dst_offset; /* Offset in destination. Little endian format. */
> > > + /* Followed by source and destination
> >
> > Add "file names"
> >
> > >, optionally padded by
> > > + * 0, up to the total of entry_len - 4 bytes.
> > > + * Strings are 0-terminated. */
> > > + char src_dst[];
> > > +} PACKED;
> > > +
> > > +enum linker_entry_type {
> >
> > Documentation:
> >
> > ADD: increment value in DST by the address of SRC
> > useful e.g. to fill in pointer values in ACPI tables
> > SUB: decrement value in DST by the address of SRC
> > useful e.g. to fix up checksum values in ACPI tables
>
> I don't see how one could implement a checksum with just a
> subtraction. If the table is at 0x12345678 the checksum isn't
> (oldcksum-0x12345678), it's (oldcksum-0x12-0x34-0x56-0x78).
>
> -Kevin
So here's the version with shift, that should do it
correctly. Add mere 8 lines of code.
I'll look into alignment and fseg now.
diff --git a/Makefile b/Makefile
index 759bbbb..020fb2f 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ SRC16=$(SRCBOTH) system.c disk.c font.c
SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c pmm.c coreboot.c boot.c \
acpi.c smm.c mptable.c pirtable.c smbios.c pciinit.c optionroms.c mtrr.c \
lzmadecode.c bootsplash.c jpeg.c usb-hub.c paravirt.c \
- biostables.c xen.c bmp.c romfile.c csm.c
+ biostables.c xen.c bmp.c romfile.c csm.c linker.c
SRC32SEG=util.c output.c pci.c pcibios.c apm.c stacks.c
# Default compiler flags
diff --git a/src/linker.c b/src/linker.c
new file mode 100644
index 0000000..a1f473d
--- /dev/null
+++ b/src/linker.c
@@ -0,0 +1,79 @@
+#include "linker.h"
+#include "byteorder.h" // le64_to_cpu
+
+void linker_link(const char *name)
+{
+ struct linker_entry_s *entry;
+ int offset = 0;
+ int size, lsrc;
+ void *data = romfile_loadfile(name, &size);
+ struct romfile_s *src, *dst;
+ u32 dst_offset;
+ u64 val, buf;
+ if (!data)
+ return;
+
+ for (offset = 0; offset < size; offset += entry->size) {
+ entry = data + offset;
+ /* Entry must have some data. If not - skip it. */
+ if (entry->size <= sizeof *entry)
+ continue;
+ /* Check that entry fits in buffer. */
+ if (offset + entry->size > size) {
+ warn_internalerror();
+ break;
+ }
+ /* Skip any command that we don't recognize. */
+ if (entry->reserved1 || entry->reserved2)
+ continue;
+ if (entry->bytes != 1 &&
+ entry->bytes != 2 &&
+ entry->bytes != 4 &&
+ entry->bytes != 8)
+ continue;
+ if (entry->shift > 63)
+ continue;
+ if (entry->type != LINKER_ENTRY_TYPE_ADD &&
+ entry->type != LINKER_ENTRY_TYPE_SUB)
+ continue;
+ if (entry->format != LINKER_ENTRY_FORMAT_LE)
+ continue;
+ /* Last byte must be 0 */
+ if (entry->src_dst[entry->size - 1]) {
+ warn_internalerror();
+ continue;
+ }
+ lsrc = strlen(entry->src_dst);
+ if (!lsrc || lsrc + 1 + sizeof *entry >= entry->size) {
+ warn_internalerror();
+ continue;
+ }
+ src = romfile_find(entry->src_dst);
+ dst = romfile_find(entry->src_dst + lsrc + 1);
+ if (!src || !dst) {
+ warn_internalerror();
+ continue;
+ }
+ if (!src->data || !dst->data) {
+ warn_internalerror();
+ continue;
+ }
+ dst_offset = le32_to_cpu(entry->dst_offset);
+ if (dst->size < dst_offset + entry->bytes) {
+ warn_internalerror();
+ continue;
+ }
+ buf = 0;
+ memcpy(&buf, dst->data + dst_offset, entry->bytes);
+ val = ((u64)(unsigned long)src->data) >> entry->shift;
+ buf = le64_to_cpu(buf);
+ if (entry->type == LINKER_ENTRY_TYPE_ADD)
+ buf += val;
+ else
+ buf -= val;
+ buf = cpu_to_le64(val);
+ memcpy(dst->data + dst_offset, &buf, entry->bytes);
+ }
+
+ free(data);
+}
diff --git a/src/linker.h b/src/linker.h
new file mode 100644
index 0000000..2bb376d
--- /dev/null
+++ b/src/linker.h
@@ -0,0 +1,29 @@
+#include "types.h" // u8
+#include "util.h" // romfile_s
+
+/* ROM file linker interface. Linker uses little endian format */
+struct linker_entry_s {
+ u8 size; /* size in bytes including the header */
+ u8 bytes; /* How many bytes to change. Can be 1,2,4 or 8. */
+ u8 shift; /* Shift source address right by this many bits. 0-63. */
+ u8 type;
+ u8 format;
+ u8 reserved1;
+ u16 reserved2;
+ u64 dst_offset; /* Offset in destination. Little endian format. */
+ /* Followed by source and destination, optionally padded by
+ * 0, up to the total of entry_len - 4 bytes.
+ * Strings are 0-terminated. */
+ char src_dst[];
+} PACKED;
+
+enum linker_entry_type {
+ LINKER_ENTRY_TYPE_ADD = 0x0,
+ LINKER_ENTRY_TYPE_SUB = 0x1,
+};
+
+enum linker_entry_format {
+ LINKER_ENTRY_FORMAT_LE = 0x0,
+};
+
+void linker_link(const char *name);
diff --git a/src/util.h b/src/util.h
index 996c29a..7b50c38 100644
--- a/src/util.h
+++ b/src/util.h
@@ -436,6 +436,7 @@ struct romfile_s {
char name[128];
u32 size;
int (*copy)(struct romfile_s *file, void *dest, u32 maxlen);
+ void *data;
};
void romfile_add(struct romfile_s *file);
struct romfile_s *romfile_findprefix(const char *prefix, struct romfile_s *prev);
More information about the SeaBIOS
mailing list