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>
This commit is contained in:
parent
4eb84cf878
commit
894977b2cd
|
@ -373,12 +373,34 @@ void acpigen_write_opregion(struct opregion *opreg)
|
||||||
acpigen_write_integer(opreg->regionlen);
|
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,
|
static void acpigen_write_field_offset(uint32_t offset,
|
||||||
uint32_t current_bit_pos)
|
uint32_t current_bit_pos)
|
||||||
{
|
{
|
||||||
uint32_t diff_bits;
|
uint32_t diff_bits;
|
||||||
uint8_t i, j;
|
|
||||||
uint8_t emit[4];
|
|
||||||
|
|
||||||
if (offset < current_bit_pos) {
|
if (offset < current_bit_pos) {
|
||||||
printk(BIOS_WARNING, "%s: Cannot move offset backward",
|
printk(BIOS_WARNING, "%s: Cannot move offset backward",
|
||||||
|
@ -394,24 +416,14 @@ static void acpigen_write_field_offset(uint32_t offset,
|
||||||
return;
|
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);
|
acpigen_emit_byte(0);
|
||||||
for (j = 0; j < i; j++)
|
acpigen_write_field_length(diff_bits);
|
||||||
acpigen_emit_byte(emit[j]);
|
}
|
||||||
|
|
||||||
|
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++) {
|
for (i = 0; i < count; i++) {
|
||||||
switch (l[i].type) {
|
switch (l[i].type) {
|
||||||
case NAME_STRING:
|
case NAME_STRING:
|
||||||
acpigen_emit_simple_namestring(l[i].name);
|
acpigen_write_field_name(l[i].name, l[i].bits);
|
||||||
acpigen_emit_byte(l[i].bits);
|
|
||||||
current_bit_pos += l[i].bits;
|
current_bit_pos += l[i].bits;
|
||||||
break;
|
break;
|
||||||
case OFFSET:
|
case OFFSET:
|
||||||
|
|
Loading…
Reference in New Issue