x86/acpigen: Fix acpigen_write_field
The current code doesn't work for field with size > 0x3f.
Fix that by using the correct syntax, reverse engineered using iasl.
Refactor to reuse existing code.
Tested on GNU Linux 4.9 and iasl.
Change-Id: Iac3600f184e6bd36a2bcb85753110692fbcbe4b6
Signed-off-by: Patrick Rudolph <siro@das-labor.org>
Reviewed-on: https://review.coreboot.org/19435
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Reviewed-by: Sumeet R Pawnikar <sumeet.r.pawnikar@intel.com>
diff --git a/src/arch/x86/acpigen.c b/src/arch/x86/acpigen.c
index 59bfee3..f9690b3 100644
--- a/src/arch/x86/acpigen.c
+++ b/src/arch/x86/acpigen.c
@@ -373,12 +373,34 @@
acpigen_write_integer(opreg->regionlen);
}
+static void acpigen_write_field_length(uint32_t len)
+{
+ uint8_t i, j;
+ uint8_t emit[4];
+
+ i = 1;
+ if (len < 0x40) {
+ emit[0] = len & 0x3F;
+ } else {
+ emit[0] = len & 0xF;
+ len >>= 4;
+ while (len) {
+ emit[i] = len & 0xFF;
+ i++;
+ len >>= 8;
+ }
+ }
+ /* Update bit 7:6 : Number of bytes followed by emit[0] */
+ emit[0] |= (i - 1) << 6;
+
+ for (j = 0; j < i; j++)
+ acpigen_emit_byte(emit[j]);
+}
+
static void acpigen_write_field_offset(uint32_t offset,
uint32_t current_bit_pos)
{
uint32_t diff_bits;
- uint8_t i, j;
- uint8_t emit[4];
if (offset < current_bit_pos) {
printk(BIOS_WARNING, "%s: Cannot move offset backward",
@@ -394,24 +416,14 @@
return;
}
- i = 1;
- if (diff_bits < 0x40) {
- emit[0] = diff_bits & 0x3F;
- } else {
- emit[0] = diff_bits & 0xF;
- diff_bits >>= 4;
- while (diff_bits) {
- emit[i] = diff_bits & 0xFF;
- i++;
- diff_bits >>= 8;
- }
- }
- /* Update bit 7:6 : Number of bytes followed by emit[0] */
- emit[0] |= (i - 1) << 6;
-
acpigen_emit_byte(0);
- for (j = 0; j < i; j++)
- acpigen_emit_byte(emit[j]);
+ acpigen_write_field_length(diff_bits);
+}
+
+static void acpigen_write_field_name(const char *name, uint32_t size)
+{
+ acpigen_emit_simple_namestring(name);
+ acpigen_write_field_length(size);
}
/*
@@ -452,8 +464,7 @@
for (i = 0; i < count; i++) {
switch (l[i].type) {
case NAME_STRING:
- acpigen_emit_simple_namestring(l[i].name);
- acpigen_emit_byte(l[i].bits);
+ acpigen_write_field_name(l[i].name, l[i].bits);
current_bit_pos += l[i].bits;
break;
case OFFSET: