Red Bear OS — microkernel OS in Rust, based on Redox

Derivative of Redox OS (https://www.redox-os.org) adding:
- AMD GPU driver (amdgpu) via LinuxKPI compat layer
- ext4 filesystem support (ext4d scheme daemon)
- ACPI fixes for AMD bare metal (x2APIC, DMAR, IVRS, MCFG)
- Custom branding (hostname, os-release, boot identity)

Build system is full upstream Redox with RBOS overlay in local/.
Patches for kernel, base, and relibc are symlinked from local/patches/
and protected from make clean/distclean. Custom recipes live in
local/recipes/ with symlinks into the recipes/ search path.

Build:  make all CONFIG_NAME=redbear-full
Sync:   ./local/scripts/sync-upstream.sh
This commit is contained in:
2026-04-12 19:05:00 +01:00
commit 50b731f1b7
3392 changed files with 98327 additions and 0 deletions
@@ -0,0 +1,427 @@
#include "redox_glue.h"
/* Global state */
static struct drm_device g_drm_dev;
static struct device g_device;
static struct pci_dev *g_pci_dev;
static void __iomem *g_mmio_base;
static size_t g_mmio_size;
static u64 g_fb_phys;
static size_t g_fb_size;
static int g_asic_family = -1;
/* ASIC family definitions based on device IDs */
#define ASIC_FAMILY_NAVI10 0x7310
#define ASIC_FAMILY_NAVI14 0x7340
#define ASIC_FAMILY_NAVI21 0x73A0
#define ASIC_FAMILY_NAVI22 0x73C0
#define ASIC_FAMILY_NAVI23 0x73E0
#define ASIC_FAMILY_NAVI24 0x7420
#define ASIC_FAMILY_NAVI31 0x7440
#define ASIC_FAMILY_NAVI32 0x7480
#define ASIC_FAMILY_NAVI33 0x74A0
#define AMDGPU_DC_HPD_STATUS_REG 0x4A00
#define AMDGPU_DC_MAX_CONNECTORS 4
#define AMDGPU_DC_BYTES_PER_PIXEL 4U
#define AMDGPU_DC_PIXEL_FORMAT_ARGB8888 3U
#define AMDGPU_DC_OTG_CONTROL 0x00
#define AMDGPU_DC_OTG_VIEWPORT_SIZE 0x10
#define AMDGPU_DC_OTG_VSYNC_ADJUST 0x14
#define AMDGPU_DC_OTG_H_TOTAL 0x18
#define AMDGPU_DC_OTG_V_TOTAL 0x1C
#define AMDGPU_DC_OTG_VSTARTUP 0x20
#define AMDGPU_DC_HUBP_PRIMARY_ADDR_LOW 0x00
#define AMDGPU_DC_HUBP_PRIMARY_ADDR_HIGH 0x04
#define AMDGPU_DC_HUBP_SURFACE_PITCH 0x08
#define AMDGPU_DC_HUBP_SURFACE_CONFIG 0x0C
#define AMDGPU_DC_HUBP_VIEWPORT_START 0x10
#define AMDGPU_DC_HUBP_VIEWPORT_SIZE 0x14
#define AMDGPU_DC_HUBP_FLIP_CONTROL 0x18
#define AMDGPU_DC_HUBP_FLIP_ADDR_LOW 0x1C
#define AMDGPU_DC_HUBP_FLIP_ADDR_HIGH 0x20
struct connector_info_ffi {
int id;
int connector_type;
int connector_type_id;
int connection;
int mm_width;
int mm_height;
int encoder_id;
};
struct amdgpu_redox_connector_desc {
int id;
u32 hpd_mask;
int connector_type;
int connector_type_id;
int encoder_id;
int mm_width;
int mm_height;
};
static const struct amdgpu_redox_connector_desc g_connector_descs[AMDGPU_DC_MAX_CONNECTORS] = {
{ .id = 1, .hpd_mask = 0x01, .connector_type = 10, .connector_type_id = 1, .encoder_id = 1, .mm_width = 600, .mm_height = 340 },
{ .id = 2, .hpd_mask = 0x02, .connector_type = 10, .connector_type_id = 2, .encoder_id = 2, .mm_width = 600, .mm_height = 340 },
{ .id = 3, .hpd_mask = 0x04, .connector_type = 11, .connector_type_id = 3, .encoder_id = 3, .mm_width = 600, .mm_height = 340 },
{ .id = 4, .hpd_mask = 0x08, .connector_type = 11, .connector_type_id = 4, .encoder_id = 4, .mm_width = 600, .mm_height = 340 },
};
static inline void __iomem *amdgpu_dc_reg_ptr(u32 base, u32 offset)
{
return (u8 __iomem *)g_mmio_base + base + offset;
}
static int amdgpu_dc_validate_mmio_access(u32 base, u32 offset)
{
u64 end = (u64)base + (u64)offset + sizeof(u32);
if (!g_mmio_base) {
return -ENODEV;
}
if (end > g_mmio_size) {
pr_err("amdgpu_redox: MMIO access %#x+%#x outside aperture %zu\n",
base, offset, g_mmio_size);
return -EINVAL;
}
return 0;
}
static inline void amdgpu_dc_write_reg(u32 base, u32 offset, u32 value)
{
if (amdgpu_dc_validate_mmio_access(base, offset) != 0) {
return;
}
writel(value, amdgpu_dc_reg_ptr(base, offset));
}
static inline u32 amdgpu_dc_read_reg(u32 base, u32 offset)
{
if (amdgpu_dc_validate_mmio_access(base, offset) != 0) {
return 0;
}
return readl(amdgpu_dc_reg_ptr(base, offset));
}
static inline u32 amdgpu_dc_hpd_status(void)
{
if (amdgpu_dc_validate_mmio_access(0, AMDGPU_DC_HPD_STATUS_REG) != 0) {
return 0;
}
return readl((u8 __iomem *)g_mmio_base + AMDGPU_DC_HPD_STATUS_REG);
}
/* Initialize AMD Display Core */
int amdgpu_dc_init(void *mmio_base, size_t mmio_size)
{
int ret = 0;
u32 gpu_id = 0;
const char *firmware_name = NULL;
printk("amdgpu_redox: initializing AMD Display Core\n");
if (!mmio_base || mmio_size < sizeof(u32)) {
pr_err("amdgpu_redox: invalid MMIO for DC init\n");
return -EINVAL;
}
gpu_id = readl(mmio_base);
printk("amdgpu_redox: GPU ID = %#010x\n", gpu_id);
switch (gpu_id) {
case ASIC_FAMILY_NAVI10:
g_asic_family = ASIC_FAMILY_NAVI10;
firmware_name = "dmcub_dcn20.bin";
break;
case ASIC_FAMILY_NAVI14:
g_asic_family = ASIC_FAMILY_NAVI14;
firmware_name = "dmcub_dcn20.bin";
break;
case ASIC_FAMILY_NAVI21:
g_asic_family = ASIC_FAMILY_NAVI21;
firmware_name = "dmcub_dcn31.bin";
break;
case ASIC_FAMILY_NAVI22:
g_asic_family = ASIC_FAMILY_NAVI22;
firmware_name = "dmcub_dcn31.bin";
break;
case ASIC_FAMILY_NAVI23:
g_asic_family = ASIC_FAMILY_NAVI23;
firmware_name = "dmcub_dcn31.bin";
break;
case ASIC_FAMILY_NAVI24:
g_asic_family = ASIC_FAMILY_NAVI24;
firmware_name = "dmcub_dcn31.bin";
break;
case ASIC_FAMILY_NAVI31:
g_asic_family = ASIC_FAMILY_NAVI31;
firmware_name = "dmcub_dcn31.bin";
break;
case ASIC_FAMILY_NAVI32:
g_asic_family = ASIC_FAMILY_NAVI32;
firmware_name = "dmcub_dcn31.bin";
break;
case ASIC_FAMILY_NAVI33:
g_asic_family = ASIC_FAMILY_NAVI33;
firmware_name = "dmcub_dcn31.bin";
break;
default:
pr_warn("amdgpu_redox: unknown ASIC %#010x, using DCN31 firmware\n", gpu_id);
g_asic_family = gpu_id;
firmware_name = "dmcub_dcn31.bin";
break;
}
printk("amdgpu_redox: ASIC family identified, loading firmware: %s\n", firmware_name);
{
const struct firmware *fw = NULL;
int fw_ret = request_firmware(&fw, firmware_name, NULL);
if (fw_ret != 0 || !fw) {
pr_warn("amdgpu_redox: firmware %s not available (err=%d), continuing without\n",
firmware_name, fw_ret);
} else {
printk("amdgpu_redox: firmware %s loaded (%zu bytes)\n", firmware_name, fw->size);
release_firmware(fw);
}
}
return ret;
}
/* Initialize AMD GPU hardware for display */
int amdgpu_redox_init(void *mmio_base, size_t mmio_size, uint64_t fb_phys, size_t fb_size)
{
int ret;
printk("amdgpu_redox: initializing AMD GPU display\n");
printk("amdgpu_redox: MMIO base=%p size=%zu\n", mmio_base, mmio_size);
printk("amdgpu_redox: FB phys=%#llx size=%zu\n", (unsigned long long)fb_phys, fb_size);
if (!mmio_base || mmio_size == 0) {
pr_err("amdgpu_redox: invalid MMIO mapping provided by redox-drm\n");
return -EINVAL;
}
memset(&g_drm_dev, 0, sizeof(g_drm_dev));
memset(&g_device, 0, sizeof(g_device));
g_mmio_base = mmio_base;
g_mmio_size = mmio_size;
g_fb_phys = fb_phys;
g_fb_size = fb_size;
g_pci_dev = redox_pci_find_amd_gpu();
if (!g_pci_dev) {
pr_err("amdgpu_redox: no AMD PCI device available from integration layer\n");
return -ENODEV;
}
g_pci_dev->mmio_base = g_mmio_base;
g_pci_dev->resource_start[0] = (phys_addr_t)(uintptr_t)g_mmio_base;
g_pci_dev->resource_len[0] = g_mmio_size;
g_device.pci_dev = g_pci_dev;
g_drm_dev.dev = &g_device;
ret = amdgpu_dc_init(mmio_base, mmio_size);
if (ret != 0) {
pr_err("amdgpu_redox: failed to initialize DC\n");
return ret;
}
return 0;
}
/* Cleanup */
void amdgpu_redox_cleanup(void)
{
printk("amdgpu_redox: cleanup\n");
if (g_pci_dev) {
redox_pci_dev_put(g_pci_dev);
g_pci_dev = NULL;
}
g_mmio_base = NULL;
g_mmio_size = 0;
g_fb_phys = 0;
g_fb_size = 0;
memset(&g_drm_dev, 0, sizeof(g_drm_dev));
memset(&g_device, 0, sizeof(g_device));
}
/* Get connector info — called by redox-drm */
int amdgpu_dc_detect_connectors(void)
{
int num_connectors = 0;
if (!g_mmio_base) {
pr_err("amdgpu_redox: detect_connectors called before init\n");
return -ENODEV;
}
#ifdef __redox__
u32 hpd_status = amdgpu_dc_hpd_status();
int i;
for (i = 0; i < AMDGPU_DC_MAX_CONNECTORS; ++i) {
if (hpd_status & g_connector_descs[i].hpd_mask) {
num_connectors++;
}
}
printk("amdgpu_redox: detected %d connector(s)\n", num_connectors);
#else
printk("amdgpu_redox: running on Linux, using AMD DC detection\n");
#endif
return num_connectors;
}
/* Get connector info by index */
int amdgpu_dc_get_connector_info(int idx, void *info)
{
struct connector_info_ffi *ffi_info = (struct connector_info_ffi *)info;
if (!g_mmio_base) {
pr_err("amdgpu_redox: get_connector_info called before init\n");
return -ENODEV;
}
if (idx < 0 || !ffi_info) {
return -EINVAL;
}
#ifdef __redox__
{
u32 hpd_status = amdgpu_dc_hpd_status();
int active_index = 0;
int i;
for (i = 0; i < AMDGPU_DC_MAX_CONNECTORS; ++i) {
const struct amdgpu_redox_connector_desc *desc = &g_connector_descs[i];
if (!(hpd_status & desc->hpd_mask)) {
continue;
}
if (active_index == idx) {
ffi_info->id = desc->id;
ffi_info->connector_type = desc->connector_type;
ffi_info->connector_type_id = desc->connector_type_id;
ffi_info->connection = 1;
ffi_info->mm_width = desc->mm_width;
ffi_info->mm_height = desc->mm_height;
ffi_info->encoder_id = desc->encoder_id;
return 0;
}
active_index++;
}
}
#endif
return -ENOENT;
}
/* Set CRTC mode — called by redox-drm for modesetting */
int amdgpu_dc_set_crtc(int crtc_id, uint64_t fb_addr, uint32_t width, uint32_t height)
{
printk("amdgpu_redox: set_crtc(%d, fb=%#llx, %ux%u)\n",
crtc_id,
(unsigned long long)fb_addr,
width,
height);
if (!g_mmio_base) {
pr_err("amdgpu_redox: set_crtc called before amdgpu_redox_init\n");
return -ENODEV;
}
#ifdef __redox__
const u32 bytes_per_pixel = AMDGPU_DC_BYTES_PER_PIXEL;
u32 pitch;
u32 viewport_size;
const u32 h_total = width + 160U;
const u32 v_total = height + 45U;
const u32 v_sync_start = height + 3U;
const u32 v_sync_end = v_sync_start + 5U;
const u32 v_sync_adjust = (v_sync_start & 0xFFFFU) | (v_sync_end << 16);
const u32 vstartup = v_sync_start > 1U ? (v_sync_start - 1U) : 0U;
u64 required_bytes;
if (crtc_id < 0 || crtc_id > 3) {
pr_err("amdgpu_redox: invalid crtc_id %d\n", crtc_id);
return -EINVAL;
}
if (width == 0 || height == 0 || width > 0xFFFFU || height > 0xFFFFU) {
pr_err("amdgpu_redox: invalid mode %ux%u\n", width, height);
return -EINVAL;
}
if (width > (UINT32_MAX / bytes_per_pixel)) {
pr_err("amdgpu_redox: pitch overflow for width %u\n", width);
return -EINVAL;
}
pitch = width * bytes_per_pixel;
viewport_size = (width & 0xFFFFU) | (height << 16);
required_bytes = (u64)pitch * (u64)height;
/* The Rust-side allocates scanout buffers via GTT VA space (0..256MiB).
* The display controller programs these GPU-virtual addresses directly;
* the GTT hardware translates them to physical backing pages at runtime.
* Validate only that the address + size fits in a u64 and that the
* programmed registers can hold the values. */
if (required_bytes == 0) {
pr_err("amdgpu_redox: zero-sized framebuffer for crtc %d\n", crtc_id);
return -EINVAL;
}
u32 otg_base = 0x4800 + (crtc_id * 0x800);
u32 hubp_base = 0x5800 + (crtc_id * 0x400);
u32 otg_control;
if (amdgpu_dc_validate_mmio_access(otg_base, AMDGPU_DC_OTG_VSTARTUP) != 0 ||
amdgpu_dc_validate_mmio_access(hubp_base, AMDGPU_DC_HUBP_FLIP_ADDR_HIGH) != 0) {
return -EINVAL;
}
otg_control = amdgpu_dc_read_reg(otg_base, AMDGPU_DC_OTG_CONTROL);
otg_control &= ~0x01U;
amdgpu_dc_write_reg(otg_base, AMDGPU_DC_OTG_CONTROL, otg_control);
mb();
amdgpu_dc_write_reg(hubp_base, AMDGPU_DC_HUBP_PRIMARY_ADDR_LOW, (u32)(fb_addr & 0xFFFFFFFFULL));
amdgpu_dc_write_reg(hubp_base, AMDGPU_DC_HUBP_PRIMARY_ADDR_HIGH, (u32)((fb_addr >> 32) & 0xFFFFFFFFULL));
amdgpu_dc_write_reg(hubp_base, AMDGPU_DC_HUBP_SURFACE_PITCH, pitch);
amdgpu_dc_write_reg(hubp_base, AMDGPU_DC_HUBP_SURFACE_CONFIG, AMDGPU_DC_PIXEL_FORMAT_ARGB8888);
amdgpu_dc_write_reg(hubp_base, AMDGPU_DC_HUBP_VIEWPORT_START, 0);
amdgpu_dc_write_reg(hubp_base, AMDGPU_DC_HUBP_VIEWPORT_SIZE, viewport_size);
amdgpu_dc_write_reg(hubp_base, AMDGPU_DC_HUBP_FLIP_ADDR_LOW, (u32)(fb_addr & 0xFFFFFFFFULL));
amdgpu_dc_write_reg(hubp_base, AMDGPU_DC_HUBP_FLIP_ADDR_HIGH, (u32)((fb_addr >> 32) & 0xFFFFFFFFULL));
amdgpu_dc_write_reg(hubp_base, AMDGPU_DC_HUBP_FLIP_CONTROL, 0);
amdgpu_dc_write_reg(otg_base, AMDGPU_DC_OTG_VIEWPORT_SIZE, viewport_size);
amdgpu_dc_write_reg(otg_base, AMDGPU_DC_OTG_VSYNC_ADJUST, v_sync_adjust);
amdgpu_dc_write_reg(otg_base, AMDGPU_DC_OTG_H_TOTAL, h_total);
amdgpu_dc_write_reg(otg_base, AMDGPU_DC_OTG_V_TOTAL, v_total);
amdgpu_dc_write_reg(otg_base, AMDGPU_DC_OTG_VSTARTUP, vstartup);
mb();
otg_control |= 0x01;
amdgpu_dc_write_reg(otg_base, AMDGPU_DC_OTG_CONTROL, otg_control);
printk("amdgpu_redox: CRTC %d enabled at %ux%u, fb=%#llx\n",
crtc_id, width, height, (unsigned long long)fb_addr);
#else
printk("amdgpu_redox: running on Linux, using AMD DC modesetting\n");
#endif
return 0;
}