aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/smbios/smbios.c
blob: 0275f4870539fd7361c460f3c9df9a7028b5706c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <stdint.h>
#include <kernel/graphics/vesa.h>
#include <stddef.h>
#include <kernel/io/io.h>
#include <kernel/smbios/smbios.h>

struct smbios_entry {
    int8_t signature[4];
    uint8_t checksum;
    uint8_t length;
    uint8_t major_version;
    uint8_t minor_version;
    uint8_t max_structure_size;
    int8_t entry_point_revision;
    int8_t formatted_area[5];
    int8_t entry_point_signature[5];
    uint8_t checksum2;
    uint16_t table_length;
    uint32_t table_address;
    uint16_t number_of_structures;
    uint8_t bcd_revision;
};

struct smbios_entry *smbios = 0;

size_t smbios_table_len(struct smbios_header *header) {
    size_t i;
    const char *strtab = (char *) header + header->length;
    for (i = 1; strtab[i - 1] != '\0' || strtab[i] != '\0'; i++);
    return header->length + i + 1;
}

struct smbios_entry *get_smbios() {
    if (smbios != 0) return smbios;

    char *mem = (char *) 0xF0000;
    int length, i;
    unsigned char checksum;
    while ((unsigned int) mem < 0x100000) {
        if (mem[0] == '_' && mem[1] == 'S' && mem[2] == 'M' && mem[3] == '_') {
            length = mem[5];
            checksum = 0;
            for (i = 0; i < length; i++) {
                checksum += mem[i];
            }
            if (checksum == 0) break;
        }
        mem += 16;
    }

    if ((unsigned int) mem == 0x100000) {
        warn("No SMBIOS found!");
        return 0;
    }

    smbios = (struct smbios_entry *) mem;
    if (smbios->major_version != 2) warn("Non-supported SMBIOS version");
    smbios_table((struct smbios_header *) mem);
    return smbios;
}

void smbios_table(struct smbios_header *header) {
    serial_write("\n\n");
    struct smbios_0 *table = (struct smbios_0 *) (header + sizeof(struct smbios_header));
    serial_write(table->bios_version);
}