smol-gilbraltar/kernel/tag.c

69 lines
1.5 KiB
C
Raw Normal View History

2024-12-23 00:46:17 +00:00
#include <assert.h>
#include <coherent_page.h>
#include <log.h>
#include <mbox.h>
#include <mem.h>
#include <stdbool.h>
#include <string.h>
#include <tag.h>
struct __attribute__((packed)) property_buf {
uint32_t size;
uint32_t code;
uint8_t tags[0];
};
struct __attribute__((packed)) property_tag {
uint32_t id;
uint32_t value_len;
uint32_t param_len;
};
bool gilbraltar_get_tags(void *tags, size_t len) {
struct property_buf *buf =
(struct property_buf *)get_coherent_page(PROP_MAILBOX);
uintptr_t dma = (uintptr_t)buf;
uint32_t *top = (uint32_t *)(buf->tags + len);
assert((((uintptr_t)buf) & (16 - 1)) == 0);
assert(len >= sizeof(struct property_tag) + sizeof(uint32_t));
uint32_t size = sizeof(struct property_buf) + len + sizeof(uint32_t);
assert((size & 3) == 0);
buf->size = size;
buf->code = CODE_REQUEST;
memcpy(buf->tags, tags, len);
*top = PROPTAG_END;
data_sync_barrier();
if (gilbraltar_mbox_write_read(dma) != dma)
return false;
data_mem_barrier();
if (buf->code != CODE_RESPONSE_SUCCESS)
return false;
memcpy(tags, buf->tags, len);
return true;
}
#define VALUE_LENGTH_RESPONSE (1 << 31)
bool gilbraltar_get_tag(uint32_t tag, void *buf, size_t len, size_t param_len) {
struct property_tag *hdr = buf;
hdr->id = tag;
hdr->value_len = len - sizeof(struct property_tag);
hdr->param_len = param_len & ~VALUE_LENGTH_RESPONSE;
if (!gilbraltar_get_tags(buf, len))
return false;
hdr->param_len &= ~VALUE_LENGTH_RESPONSE;
if (hdr->param_len == 0)
return false;
return true;
}