Got inspired by mmu_man's dmidecode release and added a simple identification

of BIOS32, SMBIOS, and DMI services.
Also implemented a get_bios32_service() function which you can use to get
access to that service (ie. for use by the PCI bus manager).


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10286 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2004-11-29 20:42:04 +00:00
parent 22ca5e3c35
commit 86a48e24ad
4 changed files with 210 additions and 7 deletions

View File

@ -0,0 +1,32 @@
/*
* Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef ARCH_x86_BIOS_H
#define ARCH_x86_BIOS_H
#include <SupportDefs.h>
#define BIOS32_PCI_SERVICE 'ICP$'
struct bios32_service {
uint32 base;
uint32 size;
uint32 offset;
};
#ifdef __cplusplus
extern "C" {
#endif
status_t get_bios32_service(uint32 identifier, struct bios32_service *service);
status_t bios_init(void);
#ifdef __cplusplus
}
#endif
#endif /* ARCH_x86_BIOS_H */

View File

@ -19,6 +19,7 @@ KernelStaticLibrary libx86 :
arch_vm_translation_map.c
arch_x86.S
arch_interrupts.S
bios.cpp
:
-fno-pic -Wno-unused
;

View File

@ -1,10 +1,10 @@
/*
** Copyright 2002-2004, The Haiku Team. All rights reserved.
** Distributed under the terms of the Haiku License.
**
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
* Copyright 2002-2004, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#include <KernelExport.h>
@ -17,6 +17,8 @@
#include <arch/cpu.h>
#include <arch/x86/interrupts.h>
#include <arch/x86/bios.h>
//#define TRACE_ARCH_VM
#ifdef TRACE_ARCH_VM
@ -53,7 +55,7 @@ arch_vm_init_post_area(kernel_args *args)
return B_NO_MEMORY;
}
return B_OK;
return bios_init();
}

View File

@ -0,0 +1,168 @@
/*
* Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <KernelExport.h>
#include <vm_types.h>
#include <arch/x86/bios.h>
//#define TRACE_BIOS
#ifdef TRACE_BIOS
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
struct smbios {
uint32 anchor_string;
uint8 entry_point_checksum;
uint8 entry_point_length;
struct {
uint8 major;
uint8 minor;
} version;
uint16 maximum_size;
uint8 formatted_area[5];
// this part is the legacy DMI compatible structure
uint8 dmi_anchor_string[5];
uint8 intermediate_checksum;
uint16 structure_table_size;
uint32 structure_table;
uint16 num_structures;
uint8 bcd_revision;
} _PACKED;
struct bios32 {
uint32 anchor_string;
uint32 service_directory;
uint8 revision;
uint8 size; // in "paragraph" (16 byte) units
uint8 checksum;
uint8 _reserved[5];
};
enum {
BIOS32 = '_23_',
SMBIOS = '_MS_',
DMI = '_IMD',
};
static addr_t sBiosBase;
static addr_t sBios32ServiceDirectory;
static bool
check_checksum(addr_t base, size_t length)
{
uint8 *bytes = (uint8 *)base;
uint8 sum = 0;
for (uint32 i = 0; i < length; i++)
sum += bytes[i];
return sum == 0;
}
// #pragma mark -
// public functions
/** This function fills the provided bios32_service structure with
* the values that identify BIOS service.
* Returns B_OK on successful completion, otherwise B_ERROR if
* the BIOS32 service directory is not available, or B_BAD_VALUE
* in case the identifier is not known or present.
*/
extern "C" status_t
get_bios32_service(uint32 identifier, struct bios32_service *service)
{
TRACE(("get_bios32_service(identifier = %#lx)\n", identifier));
if (sBios32ServiceDirectory == 0)
return B_ERROR;
uint32 eax = 0, ebx = 0, ecx = 0, edx = 0;
asm("movl %4, %%eax; " // set service parameters
"xorl %%ebx, %%ebx; "
"movl %5, %%ecx; "
"pushl %%cs; " // emulate far call by register
"call *%%ecx; "
"movl %%eax, %0; " // save return values
"movl %%ebx, %1; "
"movl %%ecx, %2; "
"movl %%edx, %3; "
: "=m" (eax), "=m" (ebx), "=m" (ecx), "=m" (edx)
: "m" (identifier), "m" (sBios32ServiceDirectory)
: "eax", "ebx", "ecx", "edx", "memory");
if ((eax & 0xff) != 0)
return B_BAD_VALUE;
service->base = ebx;
service->size = ecx;
service->offset = edx;
return B_OK;
}
extern "C" status_t
bios_init(void)
{
// map BIOS area 0xe0000 - 0xfffff
area_id biosArea = map_physical_memory("pc bios", (void *)0xe0000, 0x20000,
B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void **)&sBiosBase);
if (biosArea < 0)
return biosArea;
TRACE(("PC BIOS mapped to %p\n", (void *)sBiosBase));
// ToDo: add driver settings support to disable the services below
// search for available BIOS services
addr_t base = sBiosBase;
addr_t end = base + 0x20000;
while (base < end) {
switch (*(uint32 *)base) {
case BIOS32:
if (check_checksum(base, sizeof(struct bios32))) {
struct bios32 *bios32 = (struct bios32 *)base;
TRACE(("bios32 revision %d\n", bios32->revision));
TRACE(("bios32 service directory at: %lx\n", bios32->service_directory));
if (bios32->service_directory >= 0xe0000
&& bios32->service_directory <= 0xfffff)
sBios32ServiceDirectory = sBiosBase - 0xe0000 + bios32->service_directory;
}
break;
case SMBIOS:
// SMBIOS contains the legacy DMI structure, so we have to
// make sure it won't be found
base += 16;
TRACE(("probably found SMBIOS structure.\n"));
break;
case DMI:
TRACE(("probably found DMI legacy structure.\n"));
break;
}
// get on to next "paragraph"
base += 16;
}
return B_OK;
}