Integrate uACPI

This commit is contained in:
2025-08-17 18:37:57 +02:00
parent 069870cd0d
commit 92ccd189e7
166 changed files with 42104 additions and 33 deletions

View File

@ -0,0 +1,294 @@
#pragma once
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <uacpi/acpi.h>
#include <uacpi/internal/helpers.h>
#include <uacpi/status.h>
#include <uacpi/uacpi.h>
#ifdef __GNUC__
#define NORETURN __attribute__((__noreturn__))
#else
#define NORETURN
#endif
NORETURN static inline void error(const char *format, ...)
{
va_list args;
fprintf(stderr, "unexpected error: ");
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
fputc('\n', stderr);
uacpi_state_reset();
exit(1);
}
static inline void *do_malloc(size_t size)
{
void *ptr = malloc(size);
if (!ptr)
error("failed to allocate %zu bytes of memory", size);
return ptr;
}
static inline void *do_calloc(size_t nmemb, size_t size)
{
void *ptr = calloc(nmemb, size);
if (!ptr)
error("failed to allocate %zu bytes of memory", nmemb * size);
return ptr;
}
static inline void *do_realloc(void *ptr, size_t size)
{
ptr = realloc(ptr, size);
if (!ptr)
error("failed to allocate %zu bytes of memory", size);
return ptr;
}
typedef struct {
void *data;
size_t size;
} blob_t;
typedef struct {
blob_t *blobs;
size_t capacity;
size_t count;
} vector_t;
static inline void vector_init(vector_t *vector, size_t items)
{
vector->blobs = do_calloc(items, sizeof(*vector->blobs));
vector->capacity = items;
vector->count = items;
}
static inline void vector_add(vector_t *vector, void *data, size_t size)
{
if (vector->count >= vector->capacity) {
vector->capacity = vector->capacity ? vector->capacity * 2 : 8;
vector->blobs = do_realloc(
vector->blobs, vector->capacity * sizeof(*vector->blobs)
);
}
vector->blobs[vector->count].data = data;
vector->blobs[vector->count].size = size;
vector->count += 1;
}
static inline void vector_cleanup(vector_t *vector)
{
free(vector->blobs);
vector->capacity = 0;
vector->count = 0;
}
static inline void *get_container(void *value, size_t offset)
{
return value ? (void*)((char*)value - offset) : NULL;
}
#define CONTAINER(type, field, value) \
((type*)get_container((value), offsetof(type, field)))
typedef struct hash_node {
struct hash_node *prev;
struct hash_node *next;
uint64_t key;
} hash_node_t;
typedef struct {
hash_node_t **entries;
size_t capacity;
size_t count;
} hash_table_t;
static inline uint64_t make_hash(uint64_t x)
{
x *= 0xe9770214b82cf957;
x ^= x >> 47;
x *= 0x2bdd9d20d060fc9b;
x ^= x >> 44;
x *= 0x65c487023b406173;
return x;
}
static inline hash_node_t *hash_table_find(hash_table_t *table, uint64_t key)
{
hash_node_t *current;
if (!table->capacity)
return NULL;
current = table->entries[make_hash(key) % table->capacity];
while (current != NULL && current->key != key)
current = current->next;
return current;
}
#define HASH_TABLE_FIND(table, key, type, field) \
CONTAINER(type, field, hash_table_find((table), (key)))
static inline hash_node_t *hash_table_get_or_add(
hash_table_t *table, uint64_t key, size_t size, size_t offset
)
{
uint64_t hash = make_hash(key);
void *value;
hash_node_t *node;
size_t bucket;
if (table->capacity) {
hash_node_t *current = table->entries[hash % table->capacity];
while (current != NULL) {
if (current->key == key)
return current;
current = current->next;
}
}
if (table->count >= table->capacity - (table->capacity / 4)) {
size_t new_cap = table->capacity ? table->capacity * 2 : 8;
hash_node_t **new_entries = do_calloc(new_cap, sizeof(*table->entries));
size_t i;
for (i = 0; i < table->capacity; i++) {
hash_node_t *current = table->entries[i];
while (current != NULL) {
hash_node_t *next = current->next;
size_t bucket = make_hash(current->key) % new_cap;
current->prev = NULL;
current->next = new_entries[bucket];
if (current->next)
current->next->prev = current;
new_entries[bucket] = current;
current = next;
}
}
free(table->entries);
table->entries = new_entries;
table->capacity = new_cap;
}
value = do_calloc(1, size);
node = (void*)((char*)value + offset);
node->key = key;
bucket = hash % table->capacity;
node->prev = NULL;
node->next = table->entries[bucket];
if (node->next)
node->next->prev = node;
table->entries[bucket] = node;
table->count += 1;
return node;
}
#define HASH_TABLE_GET_OR_ADD(table, key, type, field) \
CONTAINER( \
type, field, \
hash_table_get_or_add( \
(table), (key), sizeof(type), offsetof(type, field) \
) \
)
static inline void hash_table_remove(
hash_table_t *table, hash_node_t *node, size_t offset
)
{
if (node->prev)
node->prev->next = node->next;
else
table->entries[make_hash(node->key) % table->capacity] = node->next;
if (node->next)
node->next->prev = node->prev;
table->count -= 1;
free((void*)((char*)node - offset));
}
#define HASH_TABLE_REMOVE(table, value, type, field) \
hash_table_remove((table), &(value)->field, offsetof(type, field))
static inline bool hash_table_empty(hash_table_t *table)
{
return table->count == 0;
}
static inline void hash_table_cleanup(hash_table_t *table)
{
free(table->entries);
table->capacity = 0;
table->count = 0;
}
extern bool g_expect_virtual_addresses;
extern uacpi_phys_addr g_rsdp;
UACPI_PACKED(struct full_xsdt {
struct acpi_sdt_hdr hdr;
struct acpi_fadt *fadt;
struct acpi_sdt_hdr *ssdts[];
})
void set_oem(char (*oemid)[6]);
void set_oem_table_id(char (*oemid_table_id)[8]);
struct full_xsdt *make_xsdt(
struct acpi_rsdp *rsdp, const char *dsdt_path, const vector_t *ssdt_paths
);
struct full_xsdt *make_xsdt_blob(
struct acpi_rsdp *rsdp, const void *dsdt, size_t dsdt_size
);
void delete_xsdt(struct full_xsdt *xsdt, size_t num_tables);
blob_t read_entire_file(const char *path, size_t min_size);
static inline void ensure_ok_status(uacpi_status st)
{
if (st == UACPI_STATUS_OK)
return;
error("uACPI error: %s", uacpi_status_to_string(st));
}
static inline const char *uacpi_log_level_to_string(uacpi_log_level lvl)
{
switch (lvl) {
case UACPI_LOG_DEBUG:
return "DEBUG";
case UACPI_LOG_TRACE:
return "TRACE";
case UACPI_LOG_INFO:
return "INFO";
case UACPI_LOG_WARN:
return "WARN";
case UACPI_LOG_ERROR:
return "ERROR";
default:
abort();
return NULL;
}
}