Пример #1
0
static inline grub_uint32_t
skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end)
{
  const grub_uint8_t *ptr0 = ptr;
  int add;
  grub_dprintf ("acpi", "Extended opcode: 0x%x\n", *ptr);
  switch (*ptr)
    {
    case GRUB_ACPI_EXTOPCODE_MUTEX:
      ptr++;
      ptr += skip_name_string (ptr, end);
      ptr++;
      break;
    case GRUB_ACPI_EXTOPCODE_OPERATION_REGION:
      ptr++;
      ptr += skip_name_string (ptr, end);
      ptr++;
      ptr += add = skip_data_ref_object (ptr, end);
      if (!add)
	return 0;
      ptr += add = skip_data_ref_object (ptr, end);
      if (!add)
	return 0;
      break;
    case GRUB_ACPI_EXTOPCODE_FIELD_OP:
    case GRUB_ACPI_EXTOPCODE_INDEX_FIELD_OP:
      ptr++;
      ptr += decode_length (ptr, 0);
      break;
    default:
      grub_printf ("Unexpected extended opcode: 0x%x\n", *ptr);
      return 0;
    }
  return ptr - ptr0;
}
Пример #2
0
static inline grub_uint32_t
skip_data_ref_object (const grub_uint8_t *ptr, const grub_uint8_t *end)
{
  grub_dprintf ("acpi", "data type = 0x%x\n", *ptr);
  switch (*ptr)
    {
    case GRUB_ACPI_OPCODE_PACKAGE:
    case GRUB_ACPI_OPCODE_BUFFER:
      return 1 + decode_length (ptr + 1, 0);
    case GRUB_ACPI_OPCODE_ZERO:
    case GRUB_ACPI_OPCODE_ONES:
    case GRUB_ACPI_OPCODE_ONE:
      return 1;
    case GRUB_ACPI_OPCODE_BYTE_CONST:
      return 2;
    case GRUB_ACPI_OPCODE_WORD_CONST:
      return 3;
    case GRUB_ACPI_OPCODE_DWORD_CONST:
      return 5;
    case GRUB_ACPI_OPCODE_STRING_CONST:
      {
	const grub_uint8_t *ptr0 = ptr;
	for (ptr++; ptr < end && *ptr; ptr++);
	if (ptr == end)
	  return 0;
	return ptr - ptr0 + 1;
      }
    default:
      if (*ptr == '^' || *ptr == '\\' || *ptr == '_'
	  || (*ptr >= 'A' && *ptr <= 'Z'))
	return skip_name_string (ptr, end);
      grub_printf ("Unknown opcode 0x%x\n", *ptr);
      return 0;
    }
}
Пример #3
0
static int
get_sleep_type (grub_uint8_t *table, grub_uint8_t *end)
{
  grub_uint8_t *ptr, *prev = table;
  int sleep_type = -1;
  
  ptr = table + sizeof (struct grub_acpi_table_header);
  while (ptr < end && prev < ptr)
    {
      int add;
      prev = ptr;
      grub_dprintf ("acpi", "Opcode 0x%x\n", *ptr);
      grub_dprintf ("acpi", "Tell %x\n", (unsigned) (ptr - table));
      switch (*ptr)
	{
	case GRUB_ACPI_OPCODE_EXTOP:
	  ptr++;
	  ptr += add = skip_ext_op (ptr, end);
	  if (!add)
	    return -1;
	  break;
	case GRUB_ACPI_OPCODE_CREATE_WORD_FIELD:
	case GRUB_ACPI_OPCODE_CREATE_BYTE_FIELD:
	  {
	    ptr += 5;
	    ptr += add = skip_data_ref_object (ptr, end);
	    if (!add)
	      return -1;
	    ptr += 4;
	    break;
	  }
	case GRUB_ACPI_OPCODE_NAME:
	  ptr++;
	  if (memcmp (ptr, "_S5_", 4) == 0 || memcmp (ptr, "\\_S5_", 4) == 0)
	    {
	      int ll;
	      grub_uint8_t *ptr2 = ptr;
	      grub_dprintf ("acpi", "S5 found\n");
	      ptr2 += skip_name_string (ptr, end);
	      if (*ptr2 != 0x12)
		{
		  grub_printf ("Unknown opcode in _S5: 0x%x\n", *ptr2);
		  return -1;
		}
	      ptr2++;
	      decode_length (ptr2, &ll);
	      ptr2 += ll;
	      ptr2++;
	      switch (*ptr2)
		{
		case GRUB_ACPI_OPCODE_ZERO:
		  sleep_type = 0;
		  break;
		case GRUB_ACPI_OPCODE_ONE:
		  sleep_type = 1;
		  break;
		case GRUB_ACPI_OPCODE_BYTE_CONST:
		  sleep_type = ptr2[1];
		  break;
		default:
		  grub_printf ("Unknown data type in _S5: 0x%x\n", *ptr2);
		  return -1;
		}
	    }
	  ptr += add = skip_name_string (ptr, end);
	  if (!add)
	    return -1;
	  ptr += add = skip_data_ref_object (ptr, end);
	  if (!add)
	    return -1;
	  break;
	case GRUB_ACPI_OPCODE_SCOPE:
	case GRUB_ACPI_OPCODE_IF:
	case GRUB_ACPI_OPCODE_METHOD:
	  {
	    ptr++;
	    ptr += decode_length (ptr, 0);
	    break;
	  }
	default:
	  grub_printf ("Unknown opcode 0x%x\n", *ptr);
	  return -1;	  
	}
    }

  grub_dprintf ("acpi", "TYP = %d\n", sleep_type);
  return sleep_type;
}
Пример #4
0
static int
get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end,
		grub_uint8_t *scope, int scope_len)
{
  grub_uint8_t *prev = table;
  
  if (!ptr)
    ptr = table + sizeof (struct grub_acpi_table_header);
  while (ptr < end && prev < ptr)
    {
      int add;
      prev = ptr;
      grub_dprintf ("acpi", "Opcode 0x%x\n", *ptr);
      grub_dprintf ("acpi", "Tell %x\n", (unsigned) (ptr - table));
      switch (*ptr)
	{
	case GRUB_ACPI_OPCODE_EXTOP:
	  ptr++;
	  ptr += add = skip_ext_op (ptr, end);
	  if (!add)
	    return -1;
	  break;
	case GRUB_ACPI_OPCODE_CREATE_WORD_FIELD:
	case GRUB_ACPI_OPCODE_CREATE_BYTE_FIELD:
	  {
	    ptr += 5;
	    ptr += add = skip_data_ref_object (ptr, end);
	    if (!add)
	      return -1;
	    ptr += 4;
	    break;
	  }
	case GRUB_ACPI_OPCODE_NAME:
	  ptr++;
	  if ((!scope || grub_memcmp (scope, "\\", scope_len) == 0) &&
	      (grub_memcmp (ptr, "_S5_", 4) == 0 || grub_memcmp (ptr, "\\_S5_", 4) == 0))
	    {
	      int ll;
	      grub_uint8_t *ptr2 = ptr;
	      grub_dprintf ("acpi", "S5 found\n");
	      ptr2 += skip_name_string (ptr, end);
	      if (*ptr2 != 0x12)
		{
		  grub_printf ("Unknown opcode in _S5: 0x%x\n", *ptr2);
		  return -1;
		}
	      ptr2++;
	      decode_length (ptr2, &ll);
	      ptr2 += ll;
	      ptr2++;
	      switch (*ptr2)
		{
		case GRUB_ACPI_OPCODE_ZERO:
		  return 0;
		case GRUB_ACPI_OPCODE_ONE:
		  return 1;
		case GRUB_ACPI_OPCODE_BYTE_CONST:
		  return ptr2[1];
		default:
		  grub_printf ("Unknown data type in _S5: 0x%x\n", *ptr2);
		  return -1;
		}
	    }
	  ptr += add = skip_name_string (ptr, end);
	  if (!add)
	    return -1;
	  ptr += add = skip_data_ref_object (ptr, end);
	  if (!add)
	    return -1;
	  break;
	case GRUB_ACPI_OPCODE_SCOPE:
	  {
	    int scope_sleep_type;
	    int ll;
	    grub_uint8_t *name;
	    int name_len;

	    ptr++;
	    add = decode_length (ptr, &ll);
	    name = ptr + ll;
	    name_len = skip_name_string (name, ptr + add);
	    if (!name_len)
	      return -1;
	    scope_sleep_type = get_sleep_type (table, name + name_len,
					       ptr + add, name, name_len);
	    if (scope_sleep_type != -2)
	      return scope_sleep_type;
	    ptr += add;
	    break;
	  }
	case GRUB_ACPI_OPCODE_IF:
	case GRUB_ACPI_OPCODE_METHOD:
	  {
	    ptr++;
	    ptr += decode_length (ptr, 0);
	    break;
	  }
	default:
	  grub_printf ("Unknown opcode 0x%x\n", *ptr);
	  return -1;	  
	}
    }

  return -2;
}