1 /* 2 * Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <KernelExport.h> 8 #include <vm/vm_types.h> 9 10 #include <arch/x86/bios.h> 11 12 13 //#define TRACE_BIOS 14 #ifdef TRACE_BIOS 15 # define TRACE(x) dprintf x 16 #else 17 # define TRACE(x) ; 18 #endif 19 20 21 struct smbios { 22 uint32 anchor_string; 23 uint8 entry_point_checksum; 24 uint8 entry_point_length; 25 struct { 26 uint8 major; 27 uint8 minor; 28 } version; 29 uint16 maximum_size; 30 uint8 formatted_area[5]; 31 32 // this part is the legacy DMI compatible structure 33 uint8 dmi_anchor_string[5]; 34 uint8 intermediate_checksum; 35 uint16 structure_table_size; 36 uint32 structure_table; 37 uint16 num_structures; 38 uint8 bcd_revision; 39 } _PACKED; 40 41 struct bios32 { 42 uint32 anchor_string; 43 uint32 service_directory; 44 uint8 revision; 45 uint8 size; // in "paragraph" (16 byte) units 46 uint8 checksum; 47 uint8 _reserved[5]; 48 }; 49 50 enum { 51 BIOS32 = '_23_', 52 SMBIOS = '_MS_', 53 DMI = '_IMD', 54 }; 55 56 57 addr_t gBiosBase; 58 static addr_t sBios32ServiceDirectory; 59 60 61 static bool 62 check_checksum(addr_t base, size_t length) 63 { 64 uint8 *bytes = (uint8 *)base; 65 uint8 sum = 0; 66 67 for (uint32 i = 0; i < length; i++) 68 sum += bytes[i]; 69 70 return sum == 0; 71 } 72 73 74 // #pragma mark - 75 // public functions 76 77 78 /** This function fills the provided bios32_service structure with 79 * the values that identify BIOS service. 80 * Returns B_OK on successful completion, otherwise B_ERROR if 81 * the BIOS32 service directory is not available, or B_BAD_VALUE 82 * in case the identifier is not known or present. 83 */ 84 85 extern "C" status_t 86 get_bios32_service(uint32 identifier, struct bios32_service *service) 87 { 88 TRACE(("get_bios32_service(identifier = %#lx)\n", identifier)); 89 90 if (sBios32ServiceDirectory == 0) 91 return B_ERROR; 92 93 uint32 eax = 0, ebx = 0, ecx = 0, edx = 0; 94 95 asm("movl %4, %%eax; " // set service parameters 96 "xorl %%ebx, %%ebx; " 97 "movl %5, %%ecx; " 98 "pushl %%cs; " // emulate far call by register 99 "call *%%ecx; " 100 "movl %%eax, %0; " // save return values 101 "movl %%ebx, %1; " 102 "movl %%ecx, %2; " 103 "movl %%edx, %3; " 104 : "=m" (eax), "=m" (ebx), "=m" (ecx), "=m" (edx) 105 : "m" (identifier), "m" (sBios32ServiceDirectory) 106 : "eax", "ebx", "ecx", "edx", "memory"); 107 108 if ((eax & 0xff) != 0) 109 return B_BAD_VALUE; 110 111 service->base = ebx; 112 service->size = ecx; 113 service->offset = edx; 114 115 return B_OK; 116 } 117 118 119 extern "C" status_t 120 bios_init(void) 121 { 122 // map BIOS area 0xe0000 - 0xfffff 123 area_id biosArea = map_physical_memory("pc bios", 0xe0000, 0x20000, 124 B_ANY_KERNEL_ADDRESS | B_WRITE_BACK_MEMORY, 125 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void **)&gBiosBase); 126 if (biosArea < 0) 127 return biosArea; 128 129 TRACE(("PC BIOS mapped to %p\n", (void *)gBiosBase)); 130 131 // ToDo: add driver settings support to disable the services below 132 133 // search for available BIOS services 134 135 addr_t base = gBiosBase; 136 addr_t end = base + 0x20000; 137 138 while (base < end) { 139 switch (*(uint32 *)base) { 140 case BIOS32: 141 if (check_checksum(base, sizeof(struct bios32))) { 142 struct bios32 *bios32 = (struct bios32 *)base; 143 144 TRACE(("bios32 revision %d\n", bios32->revision)); 145 TRACE(("bios32 service directory at: %lx\n", bios32->service_directory)); 146 147 if (bios32->service_directory >= 0xe0000 148 && bios32->service_directory <= 0xfffff) 149 sBios32ServiceDirectory = gBiosBase - 0xe0000 + bios32->service_directory; 150 } 151 break; 152 case SMBIOS: 153 // SMBIOS contains the legacy DMI structure, so we have to 154 // make sure it won't be found 155 base += 16; 156 TRACE(("probably found SMBIOS structure.\n")); 157 break; 158 case DMI: 159 TRACE(("probably found DMI legacy structure.\n")); 160 break; 161 } 162 163 // get on to next "paragraph" 164 base += 16; 165 } 166 167 return B_OK; 168 } 169 170