+2014-09-21 Valentin Dornauer <valentin@unimplemented.org>
+
+ The AML parser implements only a small subset of possible AML
+ opcodes. On the Fujitsu Lifebook E744 this and another bug in
+ the parser (incorrect handling of TermArg data types) would lead
+ to the laptop not turning off (_S5 not found).
+
+ * grub-core/commands/acpihalt.c: Support OpAlias in the AML parser;
+ in skip_ext_op(), handle some Type2Opcodes more correctly (TermArgs
+ aren't always simply strings!); Add function to skip TermArgs
+ * include/grub/acpi.h: Add new opcodes
+
2014-09-21 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/normal/main.c: Don't drop to rescue console in
}
}
+static inline grub_uint32_t
+skip_term (const grub_uint8_t *ptr, const grub_uint8_t *end)
+{
+ grub_uint32_t add;
+ const grub_uint8_t *ptr0 = ptr;
+
+ switch(*ptr)
+ {
+ case GRUB_ACPI_OPCODE_ADD:
+ case GRUB_ACPI_OPCODE_AND:
+ case GRUB_ACPI_OPCODE_CONCAT:
+ case GRUB_ACPI_OPCODE_CONCATRES:
+ case GRUB_ACPI_OPCODE_DIVIDE:
+ case GRUB_ACPI_OPCODE_INDEX:
+ case GRUB_ACPI_OPCODE_LSHIFT:
+ case GRUB_ACPI_OPCODE_MOD:
+ case GRUB_ACPI_OPCODE_MULTIPLY:
+ case GRUB_ACPI_OPCODE_NAND:
+ case GRUB_ACPI_OPCODE_NOR:
+ case GRUB_ACPI_OPCODE_OR:
+ case GRUB_ACPI_OPCODE_RSHIFT:
+ case GRUB_ACPI_OPCODE_SUBTRACT:
+ case GRUB_ACPI_OPCODE_TOSTRING:
+ case GRUB_ACPI_OPCODE_XOR:
+ /*
+ * Parameters for these opcodes: TermArg, TermArg Target, see ACPI
+ * spec r5.0, page 828f.
+ */
+ ptr++;
+ ptr += add = skip_term (ptr, end);
+ if (!add)
+ return 0;
+ ptr += add = skip_term (ptr, end);
+ if (!add)
+ return 0;
+ ptr += skip_name_string (ptr, end);
+ break;
+ default:
+ return skip_data_ref_object (ptr, end);
+ }
+ return ptr - ptr0;
+}
+
static inline grub_uint32_t
skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end)
{
ptr++;
ptr += skip_name_string (ptr, end);
ptr++;
- ptr += add = skip_data_ref_object (ptr, end);
+ ptr += add = skip_term (ptr, end);
if (!add)
return 0;
- ptr += add = skip_data_ref_object (ptr, end);
+ ptr += add = skip_term (ptr, end);
if (!add)
return 0;
break;
return ptr - ptr0;
}
+
static int
get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end,
grub_uint8_t *scope, int scope_len)
if (!add)
return -1;
break;
+ case GRUB_ACPI_OPCODE_ALIAS:
+ ptr++;
+ /* We need to skip two name strings */
+ ptr += add = skip_name_string (ptr, end);
+ if (!add)
+ return -1;
+ ptr += add = skip_name_string (ptr, end);
+ if (!add)
+ return -1;
+ break;
+
case GRUB_ACPI_OPCODE_SCOPE:
{
int scope_sleep_type;
enum
{
GRUB_ACPI_OPCODE_ZERO = 0, GRUB_ACPI_OPCODE_ONE = 1,
- GRUB_ACPI_OPCODE_NAME = 8, GRUB_ACPI_OPCODE_BYTE_CONST = 0x0a,
+ GRUB_ACPI_OPCODE_NAME = 8, GRUB_ACPI_OPCODE_ALIAS = 0x06,
+ GRUB_ACPI_OPCODE_BYTE_CONST = 0x0a,
GRUB_ACPI_OPCODE_WORD_CONST = 0x0b,
GRUB_ACPI_OPCODE_DWORD_CONST = 0x0c,
GRUB_ACPI_OPCODE_STRING_CONST = 0x0d,
GRUB_ACPI_OPCODE_BUFFER = 0x11,
GRUB_ACPI_OPCODE_PACKAGE = 0x12,
GRUB_ACPI_OPCODE_METHOD = 0x14, GRUB_ACPI_OPCODE_EXTOP = 0x5b,
+ GRUB_ACPI_OPCODE_ADD = 0x72,
+ GRUB_ACPI_OPCODE_CONCAT = 0x73,
+ GRUB_ACPI_OPCODE_SUBTRACT = 0x74,
+ GRUB_ACPI_OPCODE_MULTIPLY = 0x77,
+ GRUB_ACPI_OPCODE_DIVIDE = 0x78,
+ GRUB_ACPI_OPCODE_LSHIFT = 0x79,
+ GRUB_ACPI_OPCODE_RSHIFT = 0x7a,
+ GRUB_ACPI_OPCODE_AND = 0x7b,
+ GRUB_ACPI_OPCODE_NAND = 0x7c,
+ GRUB_ACPI_OPCODE_OR = 0x7d,
+ GRUB_ACPI_OPCODE_NOR = 0x7e,
+ GRUB_ACPI_OPCODE_XOR = 0x7f,
+ GRUB_ACPI_OPCODE_CONCATRES = 0x84,
+ GRUB_ACPI_OPCODE_MOD = 0x85,
+ GRUB_ACPI_OPCODE_INDEX = 0x88,
+ GRUB_ACPI_OPCODE_TOSTRING = 0x9c,
GRUB_ACPI_OPCODE_CREATE_WORD_FIELD = 0x8b,
GRUB_ACPI_OPCODE_CREATE_BYTE_FIELD = 0x8c,
GRUB_ACPI_OPCODE_IF = 0xa0, GRUB_ACPI_OPCODE_ONES = 0xff