1 2 #include <string.h> 3 4 #include "acpi.h" 5 #include "arch_proto.h" 6 7 typedef int ((* acpi_read_t)(phys_bytes addr, void * buff, size_t size)); 8 9 struct acpi_rsdp acpi_rsdp; 10 11 static acpi_read_t read_func; 12 13 #define MAX_RSDT 35 /* ACPI defines 35 signatures */ 14 #define SLP_EN_CODE (1 << 13) /* ACPI SLP_EN_CODE code */ 15 #define AMI_PACKAGE_OP_CODE (0x12) 16 #define AMI_NAME_OP_CODE (0x8) 17 #define AMI_BYTE_PREFIX_CODE (0xA) 18 #define AMI_PACKAGE_LENGTH_ENCODING_BITS_MASK (0xC0) 19 #define AMI_PACKAGE_LENGTH_ENCODING_BITS_SHIFT (6) 20 #define AMI_MIN_PACKAGE_LENGTH (1) 21 #define AMI_NUM_ELEMENTS_LENGTH (1) 22 #define AMI_SLP_TYPA_SHIFT (10) 23 #define AMI_SLP_TYPB_SHIFT (10) 24 #define AMI_S5_NAME_OP_OFFSET_1 (-1) 25 #define AMI_S5_NAME_OP_OFFSET_2 (-2) 26 #define AMI_S5_PACKAGE_OP_OFFSET (4) 27 #define AMI_S5_PACKET_LENGTH_OFFSET (5) 28 29 static struct acpi_rsdt { 30 struct acpi_sdt_header hdr; 31 u32_t data[MAX_RSDT]; 32 } rsdt; 33 34 static struct { 35 char signature [ACPI_SDT_SIGNATURE_LEN + 1]; 36 size_t length; 37 } sdt_trans[MAX_RSDT]; 38 39 static int sdt_count; 40 static u16_t pm1a_cnt_blk = 0; 41 static u16_t pm1b_cnt_blk = 0; 42 static u16_t slp_typa = 0; 43 static u16_t slp_typb = 0; 44 45 static int acpi_check_csum(struct acpi_sdt_header * tb, size_t size) 46 { 47 u8_t total = 0; 48 int i; 49 for (i = 0; i < size; i++) 50 total += ((unsigned char *)tb)[i]; 51 return total == 0 ? 0 : -1; 52 } 53 54 static int acpi_check_signature(const char * orig, const char * match) 55 { 56 return strncmp(orig, match, ACPI_SDT_SIGNATURE_LEN); 57 } 58 59 static u32_t acpi_phys2vir(u32_t p) 60 { 61 if(!vm_running) { 62 DEBUGEXTRA(("acpi: returning 0x%lx as vir addr\n", p)); 63 return p; 64 } 65 panic("acpi: can't get virtual address of arbitrary physical address"); 66 } 67 68 static int acpi_phys_copy(phys_bytes phys, void *target, size_t len) 69 { 70 if(!vm_running) { 71 memcpy(target, (void *) phys, len); 72 return 0; 73 } 74 panic("can't acpi_phys_copy with vm"); 75 } 76 77 static int acpi_read_sdt_at(phys_bytes addr, 78 struct acpi_sdt_header * tb, 79 size_t size, 80 const char * name) 81 { 82 struct acpi_sdt_header hdr; 83 84 /* if NULL is supplied, we only return the size of the table */ 85 if (tb == NULL) { 86 if (read_func(addr, &hdr, sizeof(struct acpi_sdt_header))) { 87 printf("ERROR acpi cannot read %s header\n", name); 88 return -1; 89 } 90 91 return hdr.length; 92 } 93 94 if (read_func(addr, tb, sizeof(struct acpi_sdt_header))) { 95 printf("ERROR acpi cannot read %s header\n", name); 96 return -1; 97 } 98 99 if (acpi_check_signature(tb->signature, name)) { 100 printf("ERROR acpi %s signature does not match\n", name); 101 return -1; 102 } 103 104 if (size < tb->length) { 105 printf("ERROR acpi buffer too small for %s\n", name); 106 return -1; 107 } 108 109 if (read_func(addr, tb, size)) { 110 printf("ERROR acpi cannot read %s\n", name); 111 return -1; 112 } 113 114 if (acpi_check_csum(tb, tb->length)) { 115 printf("ERROR acpi %s checksum does not match\n", name); 116 return -1; 117 } 118 119 return tb->length; 120 } 121 122 phys_bytes acpi_get_table_base(const char * name) 123 { 124 int i; 125 126 for(i = 0; i < sdt_count; i++) { 127 if (strncmp(name, sdt_trans[i].signature, 128 ACPI_SDT_SIGNATURE_LEN) == 0) 129 return (phys_bytes) rsdt.data[i]; 130 } 131 132 return (phys_bytes) NULL; 133 } 134 135 size_t acpi_get_table_length(const char * name) 136 { 137 int i; 138 139 for(i = 0; i < sdt_count; i++) { 140 if (strncmp(name, sdt_trans[i].signature, 141 ACPI_SDT_SIGNATURE_LEN) == 0) 142 return sdt_trans[i].length; 143 } 144 145 return 0; 146 } 147 148 static void * acpi_madt_get_typed_item(struct acpi_madt_hdr * hdr, 149 unsigned char type, 150 unsigned idx) 151 { 152 u8_t * t, * end; 153 int i; 154 155 t = (u8_t *) hdr + sizeof(struct acpi_madt_hdr); 156 end = (u8_t *) hdr + hdr->hdr.length; 157 158 i = 0; 159 while(t < end) { 160 if (type == ((struct acpi_madt_item_hdr *) t)->type) { 161 if (i == idx) 162 return t; 163 else 164 i++; 165 } 166 t += ((struct acpi_madt_item_hdr *) t)->length; 167 } 168 169 return NULL; 170 } 171 172 #if 0 173 static void * acpi_madt_get_item(struct acpi_madt_hdr * hdr, 174 unsigned idx) 175 { 176 u8_t * t, * end; 177 int i; 178 179 t = (u8_t *) hdr + sizeof(struct acpi_madt_hdr); 180 end = (u8_t *) hdr + hdr->hdr.length; 181 182 for(i = 0 ; i <= idx && t < end; i++) { 183 if (i == idx) 184 return t; 185 t += ((struct acpi_madt_item_hdr *) t)->length; 186 } 187 188 return NULL; 189 } 190 #endif 191 192 static int acpi_rsdp_test(void * buff) 193 { 194 struct acpi_rsdp * rsdp = (struct acpi_rsdp *) buff; 195 196 if (!platform_tbl_checksum_ok(buff, 20)) 197 return 0; 198 if (strncmp(rsdp->signature, "RSD PTR ", 8)) 199 return 0; 200 201 return 1; 202 } 203 204 static int get_acpi_rsdp(void) 205 { 206 u16_t ebda; 207 /* 208 * Read 40:0Eh - to find the starting address of the EBDA. 209 */ 210 acpi_phys_copy (0x40E, &ebda, sizeof(ebda)); 211 if (ebda) { 212 ebda <<= 4; 213 if(platform_tbl_ptr(ebda, ebda + 0x400, 16, &acpi_rsdp, 214 sizeof(acpi_rsdp), &machine.acpi_rsdp, 215 acpi_rsdp_test)) 216 return 1; 217 } 218 219 /* try BIOS read only mem space */ 220 if(platform_tbl_ptr(0xE0000, 0x100000, 16, &acpi_rsdp, 221 sizeof(acpi_rsdp), &machine.acpi_rsdp, 222 acpi_rsdp_test)) 223 return 1; 224 225 machine.acpi_rsdp = 0; /* RSDP cannot be found at this address therefore 226 it is a valid negative value */ 227 return 0; 228 } 229 230 static void acpi_init_poweroff(void) 231 { 232 u8_t *ptr = NULL; 233 u8_t *start = NULL; 234 u8_t *end = NULL; 235 struct acpi_fadt_header *fadt_header = NULL; 236 struct acpi_rsdt * dsdt_header = NULL; 237 char *msg = NULL; 238 239 /* Everything used here existed since ACPI spec 1.0 */ 240 /* So we can safely use them */ 241 fadt_header = (struct acpi_fadt_header *) 242 acpi_phys2vir(acpi_get_table_base("FACP")); 243 if (fadt_header == NULL) { 244 msg = "Could not load FACP"; 245 goto exit; 246 } 247 248 dsdt_header = (struct acpi_rsdt *) 249 acpi_phys2vir((phys_bytes) fadt_header->dsdt); 250 if (dsdt_header == NULL) { 251 msg = "Could not load DSDT"; 252 goto exit; 253 } 254 255 pm1a_cnt_blk = fadt_header->pm1a_cnt_blk; 256 pm1b_cnt_blk = fadt_header->pm1b_cnt_blk; 257 258 ptr = start = (u8_t *) dsdt_header->data; 259 end = start + dsdt_header->hdr.length - 4; 260 261 /* See http://forum.osdev.org/viewtopic.php?t=16990 */ 262 /* for layout of \_S5 */ 263 while (ptr < end && memcmp(ptr, "_S5_", 4) != 0) 264 ptr++; 265 266 msg = "Could not read S5 data. Use default SLP_TYPa and SLP_TYPb"; 267 if (ptr >= end || ptr == start) 268 goto exit; 269 270 /* validate AML structure */ 271 if (*(ptr + AMI_S5_PACKAGE_OP_OFFSET) != AMI_PACKAGE_OP_CODE) 272 goto exit; 273 274 if ((ptr < start + (-AMI_S5_NAME_OP_OFFSET_2) || 275 (*(ptr + AMI_S5_NAME_OP_OFFSET_2) != AMI_NAME_OP_CODE || 276 *(ptr + AMI_S5_NAME_OP_OFFSET_2 + 1) != '\\')) && 277 *(ptr + AMI_S5_NAME_OP_OFFSET_1) != AMI_NAME_OP_CODE) 278 goto exit; 279 280 ptr += AMI_S5_PACKET_LENGTH_OFFSET; 281 if (ptr >= end) 282 goto exit; 283 284 /* package length */ 285 ptr += ((*ptr & AMI_PACKAGE_LENGTH_ENCODING_BITS_MASK) >> 286 AMI_PACKAGE_LENGTH_ENCODING_BITS_SHIFT) + 287 AMI_MIN_PACKAGE_LENGTH + AMI_NUM_ELEMENTS_LENGTH; 288 if (ptr >= end) 289 goto exit; 290 291 if (*ptr == AMI_BYTE_PREFIX_CODE) 292 ptr++; /* skip byte prefix */ 293 294 slp_typa = (*ptr) << AMI_SLP_TYPA_SHIFT; 295 296 ptr++; /* move to SLP_TYPb */ 297 if (*ptr == AMI_BYTE_PREFIX_CODE) 298 ptr++; /* skip byte prefix */ 299 300 slp_typb = (*ptr) << AMI_SLP_TYPB_SHIFT; 301 302 msg = "poweroff initialized"; 303 304 exit: 305 if (msg) { 306 DEBUGBASIC(("acpi: %s\n", msg)); 307 } 308 } 309 310 void acpi_init(void) 311 { 312 int s, i; 313 read_func = acpi_phys_copy; 314 315 if (!get_acpi_rsdp()) { 316 printf("WARNING : Cannot configure ACPI\n"); 317 return; 318 } 319 320 s = acpi_read_sdt_at(acpi_rsdp.rsdt_addr, (struct acpi_sdt_header *) &rsdt, 321 sizeof(struct acpi_rsdt), ACPI_SDT_SIGNATURE(RSDT)); 322 323 sdt_count = (s - sizeof(struct acpi_sdt_header)) / sizeof(u32_t); 324 325 for (i = 0; i < sdt_count; i++) { 326 struct acpi_sdt_header hdr; 327 int j; 328 if (read_func(rsdt.data[i], &hdr, sizeof(struct acpi_sdt_header))) { 329 printf("ERROR acpi cannot read header at 0x%x\n", 330 rsdt.data[i]); 331 return; 332 } 333 334 for (j = 0 ; j < ACPI_SDT_SIGNATURE_LEN; j++) 335 sdt_trans[i].signature[j] = hdr.signature[j]; 336 sdt_trans[i].signature[ACPI_SDT_SIGNATURE_LEN] = '\0'; 337 sdt_trans[i].length = hdr.length; 338 } 339 340 acpi_init_poweroff(); 341 } 342 343 struct acpi_madt_ioapic * acpi_get_ioapic_next(void) 344 { 345 static unsigned idx = 0; 346 static struct acpi_madt_hdr * madt_hdr; 347 348 struct acpi_madt_ioapic * ret; 349 350 if (idx == 0) { 351 madt_hdr = (struct acpi_madt_hdr *) 352 acpi_phys2vir(acpi_get_table_base("APIC")); 353 if (madt_hdr == NULL) 354 return NULL; 355 } 356 357 ret = (struct acpi_madt_ioapic *) 358 acpi_madt_get_typed_item(madt_hdr, ACPI_MADT_TYPE_IOAPIC, idx); 359 if (ret) 360 idx++; 361 362 return ret; 363 } 364 365 struct acpi_madt_lapic * acpi_get_lapic_next(void) 366 { 367 static unsigned idx = 0; 368 static struct acpi_madt_hdr * madt_hdr; 369 370 struct acpi_madt_lapic * ret; 371 372 if (idx == 0) { 373 madt_hdr = (struct acpi_madt_hdr *) 374 acpi_phys2vir(acpi_get_table_base("APIC")); 375 if (madt_hdr == NULL) 376 return NULL; 377 } 378 379 for (;;) { 380 ret = (struct acpi_madt_lapic *) 381 acpi_madt_get_typed_item(madt_hdr, 382 ACPI_MADT_TYPE_LAPIC, idx); 383 if (!ret) 384 break; 385 386 idx++; 387 388 /* report only usable CPUs */ 389 if (ret->flags & 1) 390 break; 391 } 392 393 return ret; 394 } 395 396 void __k_unpaged_acpi_poweroff(void) 397 { 398 /* NO OP poweroff symbol*/ 399 } 400 401 void acpi_poweroff(void) 402 { 403 if (pm1a_cnt_blk == 0) { 404 return; 405 } 406 outw(pm1a_cnt_blk, slp_typa | SLP_EN_CODE); 407 if (pm1b_cnt_blk != 0) { 408 outw(pm1b_cnt_blk, slp_typb | SLP_EN_CODE); 409 } 410 } 411