summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Rudolph <siro@das-labor.org>2017-07-01 16:15:05 +0200
committerStefan Reinauer <stefan.reinauer@coreboot.org>2017-07-07 21:09:53 +0000
commit894977b2cda924d7db9e2819c8941e2d4cf6a9a4 (patch)
treeb9b3b626a30e0eefa4c956d586cfb83523cbe0a1
parent4eb84cf8784d77d6e5f24daeb04fa727dfbea016 (diff)
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>
-rw-r--r--src/arch/x86/acpigen.c53
1 files changed, 32 insertions, 21 deletions
diff --git a/src/arch/x86/acpigen.c b/src/arch/x86/acpigen.c
index 59bfee314b..f9690b3368 100644
--- a/src/arch/x86/acpigen.c
+++ b/src/arch/x86/acpigen.c
@@ -373,12 +373,34 @@ void acpigen_write_opregion(struct opregion *opreg)
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 @@ static void acpigen_write_field_offset(uint32_t offset,
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 @@ void acpigen_write_field(const char *name, struct fieldlist *l, size_t count,
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: