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: