btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / system / kernel / arch / x86 / 32 / bios.cpp
blob496c7a40734cbba7d61d8c8a51e91309d50c3e0f
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 */
7 #include <KernelExport.h>
8 #include <vm/vm_types.h>
10 #include <arch/x86/bios.h>
13 //#define TRACE_BIOS
14 #ifdef TRACE_BIOS
15 # define TRACE(x) dprintf x
16 #else
17 # define TRACE(x) ;
18 #endif
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];
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;
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];
50 enum {
51 BIOS32 = '_23_',
52 SMBIOS = '_MS_',
53 DMI = '_IMD',
57 addr_t gBiosBase;
58 static addr_t sBios32ServiceDirectory;
61 static bool
62 check_checksum(addr_t base, size_t length)
64 uint8 *bytes = (uint8 *)base;
65 uint8 sum = 0;
67 for (uint32 i = 0; i < length; i++)
68 sum += bytes[i];
70 return sum == 0;
74 // #pragma mark -
75 // public functions
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.
85 extern "C" status_t
86 get_bios32_service(uint32 identifier, struct bios32_service *service)
88 TRACE(("get_bios32_service(identifier = %#lx)\n", identifier));
90 if (sBios32ServiceDirectory == 0)
91 return B_ERROR;
93 uint32 eax = 0, ebx = 0, ecx = 0, edx = 0;
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");
108 if ((eax & 0xff) != 0)
109 return B_BAD_VALUE;
111 service->base = ebx;
112 service->size = ecx;
113 service->offset = edx;
115 return B_OK;
119 extern "C" status_t
120 bios_init(void)
122 // map BIOS area 0xe0000 - 0xfffff
123 area_id biosArea = map_physical_memory("pc bios", 0xe0000, 0x20000,
124 B_ANY_KERNEL_ADDRESS | B_MTR_WB,
125 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void **)&gBiosBase);
126 if (biosArea < 0)
127 return biosArea;
129 TRACE(("PC BIOS mapped to %p\n", (void *)gBiosBase));
131 // ToDo: add driver settings support to disable the services below
133 // search for available BIOS services
135 addr_t base = gBiosBase;
136 addr_t end = base + 0x20000;
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;
144 TRACE(("bios32 revision %d\n", bios32->revision));
145 TRACE(("bios32 service directory at: %lx\n", bios32->service_directory));
147 if (bios32->service_directory >= 0xe0000
148 && bios32->service_directory <= 0xfffff)
149 sBios32ServiceDirectory = gBiosBase - 0xe0000 + bios32->service_directory;
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;
163 // get on to next "paragraph"
164 base += 16;
167 return B_OK;