Annotation of Gnu-Mach/i386/i386at/acpihalt.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *  GRUB  --  GRand Unified Bootloader
                      3:  *  Copyright (C) 2010  Free Software Foundation, Inc.
                      4:  *
                      5:  *  GRUB is free software: you can redistribute it and/or modify
                      6:  *  it under the terms of the GNU General Public License as published by
                      7:  *  the Free Software Foundation, either version 3 of the License, or
                      8:  *  (at your option) any later version.
                      9:  *
                     10:  *  GRUB is distributed in the hope that it will be useful,
                     11:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
                     12:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     13:  *  GNU General Public License for more details.
                     14:  *
                     15:  *  You should have received a copy of the GNU General Public License
                     16:  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
                     17:  */
                     18: 
                     19: #include <grub/glue.h>
                     20: 
                     21: #ifdef GRUB_DSDT_TEST
                     22: #include <stdio.h>
                     23: #include <unistd.h>
                     24: #include <stdlib.h>
                     25: #include <stdint.h>
                     26: #include <string.h>
                     27: #include <errno.h>
                     28: 
                     29: #define grub_dprintf(cond, args...) printf ( args )
                     30: #define grub_printf printf
                     31: typedef uint64_t grub_uint64_t;
                     32: typedef uint32_t grub_uint32_t;
                     33: typedef uint16_t grub_uint16_t;
                     34: typedef uint8_t grub_uint8_t;
                     35: 
                     36: #endif
                     37: 
                     38: #include <grub/acpi.h>
                     39: #ifndef GRUB_DSDT_TEST
                     40: #include <grub/i18n.h>
                     41: #else
                     42: #define _(x) x
                     43: #define N_(x) x
                     44: #endif
                     45: 
                     46: #ifndef GRUB_DSDT_TEST
                     47: #include <grub/mm.h>
                     48: #include <grub/misc.h>
                     49: #include <grub/time.h>
                     50: #include <grub/cpu/io.h>
                     51: #endif
                     52: 
                     53: static inline grub_uint32_t
                     54: decode_length (const grub_uint8_t *ptr, int *numlen)
                     55: {
                     56:   int num_bytes, i;
                     57:   grub_uint32_t ret;
                     58:   if (*ptr < 64)
                     59:     {
                     60:       if (numlen)
                     61:        *numlen = 1;
                     62:       return *ptr;
                     63:     }
                     64:   num_bytes = *ptr >> 6;
                     65:   if (numlen)
                     66:     *numlen = num_bytes + 1;
                     67:   ret = *ptr & 0xf;
                     68:   ptr++;
                     69:   for (i = 0; i < num_bytes; i++)
                     70:     {
                     71:       ret |= *ptr << (8 * i + 4);
                     72:       ptr++;
                     73:     }
                     74:   return ret;
                     75: }
                     76: 
                     77: static inline grub_uint32_t
                     78: skip_name_string (const grub_uint8_t *ptr, const grub_uint8_t *end)
                     79: {
                     80:   const grub_uint8_t *ptr0 = ptr;
                     81:   
                     82:   while (ptr < end && (*ptr == '^' || *ptr == '\\'))
                     83:     ptr++;
                     84:   switch (*ptr)
                     85:     {
                     86:     case '.':
                     87:       ptr++;
                     88:       ptr += 8;
                     89:       break;
                     90:     case '/':
                     91:       ptr++;
                     92:       ptr += 1 + (*ptr) * 4;
                     93:       break;
                     94:     case 0:
                     95:       ptr++;
                     96:       break;
                     97:     default:
                     98:       ptr += 4;
                     99:       break;
                    100:     }
                    101:   return ptr - ptr0;
                    102: }
                    103: 
                    104: static inline grub_uint32_t
                    105: skip_data_ref_object (const grub_uint8_t *ptr, const grub_uint8_t *end)
                    106: {
                    107:   grub_dprintf ("acpi", "data type = 0x%x\n", *ptr);
                    108:   switch (*ptr)
                    109:     {
                    110:     case GRUB_ACPI_OPCODE_PACKAGE:
                    111:     case GRUB_ACPI_OPCODE_BUFFER:
                    112:       return 1 + decode_length (ptr + 1, 0);
                    113:     case GRUB_ACPI_OPCODE_ZERO:
                    114:     case GRUB_ACPI_OPCODE_ONES:
                    115:     case GRUB_ACPI_OPCODE_ONE:
                    116:       return 1;
                    117:     case GRUB_ACPI_OPCODE_BYTE_CONST:
                    118:       return 2;
                    119:     case GRUB_ACPI_OPCODE_WORD_CONST:
                    120:       return 3;
                    121:     case GRUB_ACPI_OPCODE_DWORD_CONST:
                    122:       return 5;
                    123:     case GRUB_ACPI_OPCODE_STRING_CONST:
                    124:       {
                    125:        const grub_uint8_t *ptr0 = ptr;
                    126:        for (ptr++; ptr < end && *ptr; ptr++);
                    127:        if (ptr == end)
                    128:          return 0;
                    129:        return ptr - ptr0 + 1;
                    130:       }
                    131:     default:
                    132:       if (*ptr == '^' || *ptr == '\\' || *ptr == '_'
                    133:          || (*ptr >= 'A' && *ptr <= 'Z'))
                    134:        return skip_name_string (ptr, end);
                    135:       grub_printf ("Unknown opcode 0x%x\n", *ptr);
                    136:       return 0;
                    137:     }
                    138: }
                    139: 
                    140: static inline grub_uint32_t
                    141: skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end)
                    142: {
                    143:   const grub_uint8_t *ptr0 = ptr;
                    144:   int add;
                    145:   grub_dprintf ("acpi", "Extended opcode: 0x%x\n", *ptr);
                    146:   switch (*ptr)
                    147:     {
                    148:     case GRUB_ACPI_EXTOPCODE_MUTEX:
                    149:       ptr++;
                    150:       ptr += skip_name_string (ptr, end);
                    151:       ptr++;
                    152:       break;
                    153:     case GRUB_ACPI_EXTOPCODE_EVENT_OP:
                    154:       ptr++;
                    155:       ptr += skip_name_string (ptr, end);
                    156:       break;
                    157:     case GRUB_ACPI_EXTOPCODE_OPERATION_REGION:
                    158:       ptr++;
                    159:       ptr += skip_name_string (ptr, end);
                    160:       ptr++;
                    161:       ptr += add = skip_data_ref_object (ptr, end);
                    162:       if (!add)
                    163:        return 0;
                    164:       ptr += add = skip_data_ref_object (ptr, end);
                    165:       if (!add)
                    166:        return 0;
                    167:       break;
                    168:     case GRUB_ACPI_EXTOPCODE_FIELD_OP:
                    169:     case GRUB_ACPI_EXTOPCODE_DEVICE_OP:
                    170:     case GRUB_ACPI_EXTOPCODE_PROCESSOR_OP:
                    171:     case GRUB_ACPI_EXTOPCODE_POWER_RES_OP:
                    172:     case GRUB_ACPI_EXTOPCODE_THERMAL_ZONE_OP:
                    173:     case GRUB_ACPI_EXTOPCODE_INDEX_FIELD_OP:
                    174:     case GRUB_ACPI_EXTOPCODE_BANK_FIELD_OP:
                    175:       ptr++;
                    176:       ptr += decode_length (ptr, 0);
                    177:       break;
                    178:     default:
                    179:       grub_printf ("Unexpected extended opcode: 0x%x\n", *ptr);
                    180:       return 0;
                    181:     }
                    182:   return ptr - ptr0;
                    183: }
                    184: 
                    185: static int
                    186: get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end,
                    187:                grub_uint8_t *scope, int scope_len)
                    188: {
                    189:   grub_uint8_t *prev = table;
                    190:   
                    191:   if (!ptr)
                    192:     ptr = table + sizeof (struct grub_acpi_table_header);
                    193:   while (ptr < end && prev < ptr)
                    194:     {
                    195:       int add;
                    196:       prev = ptr;
                    197:       grub_dprintf ("acpi", "Opcode 0x%x\n", *ptr);
                    198:       grub_dprintf ("acpi", "Tell %x\n", (unsigned) (ptr - table));
                    199:       switch (*ptr)
                    200:        {
                    201:        case GRUB_ACPI_OPCODE_EXTOP:
                    202:          ptr++;
                    203:          ptr += add = skip_ext_op (ptr, end);
                    204:          if (!add)
                    205:            return -1;
                    206:          break;
                    207:        case GRUB_ACPI_OPCODE_CREATE_WORD_FIELD:
                    208:        case GRUB_ACPI_OPCODE_CREATE_BYTE_FIELD:
                    209:          {
                    210:            ptr += 5;
                    211:            ptr += add = skip_data_ref_object (ptr, end);
                    212:            if (!add)
                    213:              return -1;
                    214:            ptr += 4;
                    215:            break;
                    216:          }
                    217:        case GRUB_ACPI_OPCODE_NAME:
                    218:          ptr++;
                    219:          if ((!scope || grub_memcmp (scope, "\\", scope_len) == 0) &&
                    220:              (grub_memcmp (ptr, "_S5_", 4) == 0 || grub_memcmp (ptr, "\\_S5_", 4) == 0))
                    221:            {
                    222:              int ll;
                    223:              grub_uint8_t *ptr2 = ptr;
                    224:              grub_dprintf ("acpi", "S5 found\n");
                    225:              ptr2 += skip_name_string (ptr, end);
                    226:              if (*ptr2 != 0x12)
                    227:                {
                    228:                  grub_printf ("Unknown opcode in _S5: 0x%x\n", *ptr2);
                    229:                  return -1;
                    230:                }
                    231:              ptr2++;
                    232:              decode_length (ptr2, &ll);
                    233:              ptr2 += ll;
                    234:              ptr2++;
                    235:              switch (*ptr2)
                    236:                {
                    237:                case GRUB_ACPI_OPCODE_ZERO:
                    238:                  return 0;
                    239:                case GRUB_ACPI_OPCODE_ONE:
                    240:                  return 1;
                    241:                case GRUB_ACPI_OPCODE_BYTE_CONST:
                    242:                  return ptr2[1];
                    243:                default:
                    244:                  grub_printf ("Unknown data type in _S5: 0x%x\n", *ptr2);
                    245:                  return -1;
                    246:                }
                    247:            }
                    248:          ptr += add = skip_name_string (ptr, end);
                    249:          if (!add)
                    250:            return -1;
                    251:          ptr += add = skip_data_ref_object (ptr, end);
                    252:          if (!add)
                    253:            return -1;
                    254:          break;
                    255:        case GRUB_ACPI_OPCODE_SCOPE:
                    256:          {
                    257:            int scope_sleep_type;
                    258:            int ll;
                    259:            grub_uint8_t *name;
                    260:            int name_len;
                    261: 
                    262:            ptr++;
                    263:            add = decode_length (ptr, &ll);
                    264:            name = ptr + ll;
                    265:            name_len = skip_name_string (name, ptr + add);
                    266:            if (!name_len)
                    267:              return -1;
                    268:            scope_sleep_type = get_sleep_type (table, name + name_len,
                    269:                                               ptr + add, name, name_len);
                    270:            if (scope_sleep_type != -2)
                    271:              return scope_sleep_type;
                    272:            ptr += add;
                    273:            break;
                    274:          }
                    275:        case GRUB_ACPI_OPCODE_IF:
                    276:        case GRUB_ACPI_OPCODE_METHOD:
                    277:          {
                    278:            ptr++;
                    279:            ptr += decode_length (ptr, 0);
                    280:            break;
                    281:          }
                    282:        default:
                    283:          grub_printf ("Unknown opcode 0x%x\n", *ptr);
                    284:          return -1;      
                    285:        }
                    286:     }
                    287: 
                    288:   return -2;
                    289: }
                    290: 
                    291: #ifdef GRUB_DSDT_TEST
                    292: int
                    293: main (int argc, char **argv)
                    294: {
                    295:   FILE *f;
                    296:   size_t len;
                    297:   unsigned char *buf;
                    298:   if (argc < 2)
                    299:     printf ("Usage: %s FILE\n", argv[0]);
                    300:   f = grub_util_fopen (argv[1], "rb");
                    301:   if (!f)
                    302:     {
                    303:       printf ("Couldn't open file\n");
                    304:       return 1;
                    305:     }
                    306:   fseek (f, 0, SEEK_END);
                    307:   len = ftell (f);
                    308:   fseek (f, 0, SEEK_SET);
                    309:   buf = malloc (len);
                    310:   if (!buf)
                    311:     {
                    312:       printf (_("error: %s.\n"), _("out of memory"));
                    313:       fclose (f);
                    314:       return 2;
                    315:     }
                    316:   if (fread (buf, 1, len, f) != len)
                    317:     {
                    318:       printf (_("cannot read `%s': %s"), argv[1], strerror (errno));
                    319:       free (buf);
                    320:       fclose (f);
                    321:       return 2;
                    322:     }
                    323: 
                    324:   printf ("Sleep type = %d\n", get_sleep_type (buf, NULL, buf + len, NULL, 0));
                    325:   free (buf);
                    326:   fclose (f);
                    327:   return 0;
                    328: }
                    329: 
                    330: #else
                    331: 
                    332: void
                    333: grub_acpi_halt (void)
                    334: {
                    335:   struct grub_acpi_rsdp_v20 *rsdp2;
                    336:   struct grub_acpi_rsdp_v10 *rsdp1;
                    337:   struct grub_acpi_table_header *rsdt;
                    338:   grub_uint32_t *entry_ptr;
                    339:   grub_uint32_t port = 0;
                    340:   int sleep_type = -1;
                    341: 
                    342:   rsdp2 = grub_acpi_get_rsdpv2 ();
                    343:   if (rsdp2)
                    344:     rsdp1 = &(rsdp2->rsdpv1);
                    345:   else
                    346:     rsdp1 = grub_acpi_get_rsdpv1 ();
                    347:   grub_dprintf ("acpi", "rsdp1=%p\n", rsdp1);
                    348:   if (!rsdp1)
                    349:     return;
                    350: 
                    351:   rsdt = (struct grub_acpi_table_header *)
                    352:     io_map_cached (rsdp1->rsdt_addr, sizeof *rsdt);
                    353:   rsdt = (struct grub_acpi_table_header *)
                    354:     io_map_cached (rsdp1->rsdt_addr, rsdt->length);
                    355: 
                    356:   for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
                    357:        entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt)
                    358:                                      + rsdt->length);
                    359:        entry_ptr++)
                    360:     {
                    361:       if (grub_memcmp ((void *) io_map_cached (*entry_ptr, 4),
                    362:                       "FACP", 4) == 0)
                    363:        {
                    364:          struct grub_acpi_fadt *fadt = (struct grub_acpi_fadt *)
                    365:            io_map_cached (*entry_ptr, sizeof *fadt);
                    366: 
                    367:          struct grub_acpi_table_header *dsdt =
                    368:            (struct grub_acpi_table_header *)
                    369:            io_map_cached (fadt->dsdt_addr, sizeof *dsdt);
                    370:          grub_uint8_t *buf = (grub_uint8_t *)
                    371:            io_map_cached (fadt->dsdt_addr, dsdt->length);
                    372: 
                    373:          port = fadt->pm1a;
                    374: 
                    375:          grub_dprintf ("acpi", "PM1a port=%x\n", port);
                    376: 
                    377:          if (grub_memcmp (dsdt->signature, "DSDT",
                    378:                           sizeof (dsdt->signature)) == 0
                    379:              && sleep_type < 0)
                    380:            sleep_type = get_sleep_type (buf, NULL, buf + dsdt->length,
                    381:                                         NULL, 0);
                    382:        }
                    383:       else
                    384:        if (grub_memcmp ((void *) io_map_cached (*entry_ptr, 4), "SSDT", 4) == 0
                    385:            && sleep_type < 0)
                    386:        {
                    387:          struct grub_acpi_table_header *ssdt
                    388:            = (struct grub_acpi_table_header *) (grub_addr_t)
                    389:            io_map_cached (*entry_ptr, sizeof *ssdt);
                    390:          grub_uint8_t *buf = (grub_uint8_t *)
                    391:            io_map_cached (*entry_ptr, ssdt->length);
                    392: 
                    393:          grub_dprintf ("acpi", "SSDT = %p\n", ssdt);
                    394: 
                    395:          sleep_type = get_sleep_type (buf, NULL, buf + ssdt->length, NULL, 0);
                    396:        }
                    397:     }
                    398: 
                    399:   grub_dprintf ("acpi", "SLP_TYP = %d, port = 0x%x\n", sleep_type, port);
                    400:   if (port && sleep_type >= 0 && sleep_type < 8)
                    401:     grub_outw (GRUB_ACPI_SLP_EN | (sleep_type << GRUB_ACPI_SLP_TYP_OFFSET),
                    402:               port & 0xffff);
                    403: 
                    404:   grub_millisleep (1500);
                    405: 
                    406:   /* TRANSLATORS: It's computer shutdown using ACPI, not disabling ACPI.  */
                    407:   grub_puts_ (N_("ACPI shutdown failed"));
                    408: }
                    409: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.