Compare commits
3 Commits
6dd3c506f1
...
37f4243c61
Author | SHA1 | Date | |
---|---|---|---|
37f4243c61 | |||
4da268b255 | |||
5c7693dac5 |
3
Makefile
3
Makefile
@ -14,6 +14,9 @@ override CFLAGS += \
|
||||
-pipe \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Wshadow \
|
||||
-Wstrict-aliasing \
|
||||
-pedantic \
|
||||
-std=c99 \
|
||||
-ffreestanding \
|
||||
-fno-stack-protector \
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include <string.h>
|
||||
#include <fb.h>
|
||||
|
||||
// The buffer must be 16-byte aligned as only the upper 28 bits of the address can be passed via the mailbox
|
||||
/* The buffer must be 16-byte aligned as only the upper 28 bits of the address can be passed via the mailbox */
|
||||
volatile unsigned int __attribute__((aligned(16))) mbox[36];
|
||||
|
||||
unsigned int width, height, pitch, bpp, rgb;
|
||||
@ -37,17 +37,17 @@ void pixel_draw(int x, int y, int r, int g, int b) {
|
||||
}
|
||||
|
||||
unsigned int mbox_call(unsigned char ch) {
|
||||
unsigned int m = ((unsigned int)((long) &mbox) &~ 0xF) | (ch & 0xF); // 28-bit address (MSB), 4-bit value (LSB)
|
||||
unsigned int m = ((unsigned int)((long) &mbox) &~ 0xF) | (ch & 0xF); /* 28-bit address (MSB), 4-bit value (LSB) */
|
||||
|
||||
while (1) if(!(mmio_read(MBOX_STATUS) & MBOX_FULL)) break;
|
||||
|
||||
mmio_write(MBOX_WRITE, m);
|
||||
|
||||
while (1) {
|
||||
while (1) if(!(mmio_read(MBOX_STATUS) & MBOX_EMPTY)) break; // Wait for a reply
|
||||
while (1) if(!(mmio_read(MBOX_STATUS) & MBOX_EMPTY)) break; /* Wait for a reply */
|
||||
|
||||
if (m == mmio_read(MBOX_READ)) { // Look for a message on MBOX_READ
|
||||
if(mbox[1]==MBOX_RESPONSE) return 1; // Success!
|
||||
if (m == mmio_read(MBOX_READ)) { /* Look for a message on MBOX_READ */
|
||||
if(mbox[1]==MBOX_RESPONSE) return 1; /* Success! */
|
||||
else return 0;
|
||||
}
|
||||
}
|
||||
@ -66,14 +66,14 @@ void fb_init() {
|
||||
MBOX_CONFIG = (MBOX_BASE + 0x1C);
|
||||
MBOX_WRITE = (MBOX_BASE + 0x20);
|
||||
|
||||
mbox[0] = 35 * 4; // Length of message in bytes
|
||||
mbox[0] = 35 * 4; /* Length of message in bytes */
|
||||
mbox[1] = MBOX_REQUEST;
|
||||
|
||||
mbox[2] = MBOX_TAG_SETPHYWH;
|
||||
mbox[3] = 8; // Value size in bytes
|
||||
mbox[3] = 8; /* Value size in bytes */
|
||||
mbox[4] = 0;
|
||||
mbox[5] = 640; // Width, hardcoded for now
|
||||
mbox[6] = 480; // Height, hardcoded for now
|
||||
mbox[5] = 640; /* Width, hardcoded for now */
|
||||
mbox[6] = 480; /* Height, hardcoded for now */
|
||||
|
||||
mbox[7] = MBOX_TAG_SETVIRTWH;
|
||||
mbox[8] = 8;
|
||||
@ -84,38 +84,39 @@ void fb_init() {
|
||||
mbox[12] = MBOX_TAG_SETVIRTOFF;
|
||||
mbox[13] = 8;
|
||||
mbox[14] = 8;
|
||||
mbox[15] = 0; // X coordinate
|
||||
mbox[16] = 0; // Y coordinate
|
||||
mbox[15] = 0; /* X coordinate */
|
||||
mbox[16] = 0; /* Y coordinate */
|
||||
|
||||
mbox[17] = MBOX_TAG_SETDEPTH;
|
||||
mbox[18] = 4;
|
||||
mbox[19] = 4;
|
||||
mbox[20] = 32; // Bits per pixel
|
||||
mbox[20] = 32; /* Bits per pixel */
|
||||
|
||||
mbox[21] = MBOX_TAG_SETPXLORDR;
|
||||
mbox[22] = 4;
|
||||
mbox[23] = 4;
|
||||
mbox[24] = 1; // RGB
|
||||
mbox[24] = 1; /* RGB */
|
||||
|
||||
mbox[25] = MBOX_TAG_GETFB;
|
||||
mbox[26] = 8;
|
||||
mbox[27] = 8;
|
||||
mbox[28] = 4096; // FrameBufferInfo.pointer
|
||||
mbox[29] = 0; // FrameBufferInfo.size
|
||||
mbox[28] = 4096; /* FrameBufferInfo.pointer */
|
||||
mbox[29] = 0; /* FrameBufferInfo.size */
|
||||
|
||||
mbox[30] = MBOX_TAG_GETPITCH;
|
||||
mbox[31] = 4;
|
||||
mbox[32] = 4;
|
||||
mbox[33] = 0; // Bytes per line
|
||||
mbox[33] = 0; /* Bytes per line */
|
||||
|
||||
mbox[34] = MBOX_TAG_LAST;
|
||||
|
||||
if (mbox_call(MBOX_CH_PROP) && mbox[20] == 32 && mbox[28] != 0) { // Check if mailbox says we're good and that the depth is what we asked for and that it gave us a pointer
|
||||
mbox[28] &= 0x3FFFFFFF; // Convert GPU address to ARM address
|
||||
width = mbox[10]; // Actual physical width
|
||||
height = mbox[11]; // Actual physical height
|
||||
pitch = mbox[33]; // Number of bytes per line
|
||||
rgb = mbox[24]; // Pixel order
|
||||
/* Check if mailbox says we're good and that the depth is what we asked for and that it gave us a pointer */
|
||||
if (mbox_call(MBOX_CH_PROP) && mbox[20] == 32 && mbox[28] != 0) {
|
||||
mbox[28] &= 0x3FFFFFFF; /* Convert GPU address to ARM address */
|
||||
width = mbox[10]; /* Actual physical width */
|
||||
height = mbox[11]; /* Actual physical height */
|
||||
pitch = mbox[33]; /* Number of bytes per line */
|
||||
rgb = mbox[24]; /* Pixel order */
|
||||
fb = (unsigned char *)((long)mbox[28]);
|
||||
bpp = pitch / width;
|
||||
printf("Initialized framebuffer.\n");
|
||||
|
@ -28,16 +28,16 @@ void fdt_init() {
|
||||
}
|
||||
|
||||
fdt_prop fdt_get_prop(uint32_t* addr) {
|
||||
return (fdt_prop){
|
||||
return (fdt_prop) {
|
||||
SWAP_UINT32(*addr),
|
||||
SWAP_UINT32(*(addr+1)),
|
||||
addr+2
|
||||
addr + 2
|
||||
};
|
||||
}
|
||||
|
||||
uint32_t* fdt_get_addr(const char* path) {
|
||||
const char* fdt_strings = (void*)fdt + SWAP_UINT32(fdt->off_dt_strings);
|
||||
uint32_t* fdt_struct = (void*)fdt + SWAP_UINT32(fdt->off_dt_struct);
|
||||
const char* fdt_strings = (char*)fdt + SWAP_UINT32(fdt->off_dt_strings);
|
||||
uint32_t* fdt_struct = (uint32_t*)fdt + SWAP_UINT32(fdt->off_dt_struct);
|
||||
const uint32_t struct_size = SWAP_UINT32(fdt->size_dt_struct);
|
||||
|
||||
uint32_t* struct_ptr = fdt_struct;
|
||||
@ -51,59 +51,59 @@ uint32_t* fdt_get_addr(const char* path) {
|
||||
char* name = strtok(path_copy, "/");
|
||||
|
||||
while(name && struct_ptr < fdt_struct + struct_size) {
|
||||
// Read token
|
||||
/* Read token */
|
||||
const uint32_t token = SWAP_UINT32(*struct_ptr);
|
||||
switch(token) {
|
||||
// The beginning node is followed immediately by its name
|
||||
/* The beginning node is followed immediately by its name */
|
||||
case FDT_BEGIN_NODE:
|
||||
// Advance pointer
|
||||
/* Advance pointer */
|
||||
struct_ptr++;
|
||||
|
||||
// check if we are in the token we want
|
||||
/* check if we are in the token we want */
|
||||
if(!strcmp((char*)struct_ptr, name)) {
|
||||
name = strtok(0, "/");
|
||||
lastaddr = struct_ptr;
|
||||
}
|
||||
|
||||
// Calculate the size of the node name
|
||||
/* Calculate the size of the node name */
|
||||
name_length = strlen((char*)struct_ptr);
|
||||
// Advance pointer by size of node name aligned to 4 bytes
|
||||
/* Advance pointer by size of node name aligned to 4 bytes */
|
||||
struct_ptr += name_length / 4;
|
||||
break;
|
||||
|
||||
// Property
|
||||
/* Property */
|
||||
case FDT_PROP:
|
||||
// Advance pointer
|
||||
/* Advance pointer */
|
||||
prop_length = *++struct_ptr;
|
||||
prop_name_off = *++struct_ptr;
|
||||
|
||||
// check if we are in the token we want
|
||||
/* check if we are in the token we want */
|
||||
if(!strcmp(fdt_strings + SWAP_UINT32(prop_name_off), name)) {
|
||||
return struct_ptr-1;
|
||||
}
|
||||
// Advance pointer
|
||||
/* Advance pointer */
|
||||
struct_ptr += SWAP_UINT32(prop_length) / 4;
|
||||
break;
|
||||
|
||||
// End is followed immediately by next token
|
||||
/* End is followed immediately by next token */
|
||||
case FDT_END_NODE:
|
||||
case FDT_NOP:
|
||||
break;
|
||||
|
||||
// There can be only one FDT_END which marks the
|
||||
// end of FDT
|
||||
/* There can be only one FDT_END which marks the
|
||||
end of FDT */
|
||||
case FDT_END:
|
||||
return 0;
|
||||
}
|
||||
// Advance pointer
|
||||
/* Advance pointer */
|
||||
struct_ptr++;
|
||||
}
|
||||
return lastaddr;
|
||||
}
|
||||
|
||||
void print_fdt() {
|
||||
const char* fdt_strings = (void*)fdt + SWAP_UINT32(fdt->off_dt_strings);
|
||||
uint32_t* fdt_struct = (void*)fdt + SWAP_UINT32(fdt->off_dt_struct);
|
||||
const char* fdt_strings = (char*)fdt + SWAP_UINT32(fdt->off_dt_strings);
|
||||
uint32_t* fdt_struct = (uint32_t*)fdt + SWAP_UINT32(fdt->off_dt_struct);
|
||||
const uint32_t struct_size = SWAP_UINT32(fdt->size_dt_struct);
|
||||
|
||||
uint32_t* struct_ptr = fdt_struct;
|
||||
@ -115,23 +115,23 @@ void print_fdt() {
|
||||
uint8_t first_elem = 0;
|
||||
|
||||
while(struct_ptr < fdt_struct + struct_size) {
|
||||
// Read token
|
||||
/* Read token */
|
||||
const uint32_t token = SWAP_UINT32(*struct_ptr);
|
||||
switch(token) {
|
||||
// The beginning node is followed immediately by its name
|
||||
/* The beginning node is followed immediately by its name */
|
||||
case FDT_BEGIN_NODE:
|
||||
// Advance pointer
|
||||
/* Advance pointer */
|
||||
struct_ptr++;
|
||||
|
||||
// print tabs
|
||||
/* print tabs */
|
||||
for(int i = 0; i < tab_count; ++i) uart_puts(" ");
|
||||
// increment tab count
|
||||
/* increment tab count */
|
||||
tab_count++;
|
||||
|
||||
// Calculate the size of the node name
|
||||
/* Calculate the size of the node name */
|
||||
name_length = strlen((char*)struct_ptr);
|
||||
|
||||
// Print node name
|
||||
/* Print node name */
|
||||
if(!name_length) {
|
||||
uart_puts("/:");
|
||||
} else {
|
||||
@ -140,33 +140,33 @@ void print_fdt() {
|
||||
}
|
||||
uart_putc('\n');
|
||||
|
||||
// Advance pointer by size of node name aligned to 4 bytes
|
||||
/* Advance pointer by size of node name aligned to 4 bytes */
|
||||
struct_ptr += name_length / 4;
|
||||
break;
|
||||
|
||||
// Property
|
||||
/* Property */
|
||||
case FDT_PROP:
|
||||
// Advance pointer
|
||||
/* Advance pointer */
|
||||
prop_length = *++struct_ptr;
|
||||
prop_name_off = *++struct_ptr;
|
||||
|
||||
// print tabs
|
||||
/* print tabs */
|
||||
for(int i = 0; i < tab_count+1; ++i) uart_puts(" ");
|
||||
|
||||
// Print prop name and value
|
||||
/* Print prop name and value */
|
||||
uart_puts(fdt_strings + SWAP_UINT32(prop_name_off));
|
||||
// Value can be empty
|
||||
/* Value can be empty */
|
||||
if(prop_length) {
|
||||
uart_puts(": ");
|
||||
// Dirty hack to see if the value is a string or a number(s)
|
||||
// If the first byte of the 4 byte chunk does not fall
|
||||
// under acceptable ASCII character values, print its
|
||||
// digits one by one, else just call puts on it since
|
||||
// it is ***probably*** a string.
|
||||
/* Dirty hack to see if the value is a string or a number(s)
|
||||
If the first byte of the 4 byte chunk does not fall
|
||||
under acceptable ASCII character values, print its
|
||||
digits one by one, else just call puts on it since
|
||||
it is ***probably*** a string. */
|
||||
first_elem = (uint8_t)(SWAP_UINT32(*(struct_ptr+1)));
|
||||
// It is probably a number or an array of numbers
|
||||
// Divide length of the property by 4 to get
|
||||
// the amount of numbers and iterate over them
|
||||
/* It is probably a number or an array of numbers
|
||||
Divide length of the property by 4 to get
|
||||
the amount of numbers and iterate over them */
|
||||
if(first_elem < 0x20 || first_elem > 0x7A || !strcmp("reg", fdt_strings + SWAP_UINT32(prop_name_off))) {
|
||||
for(uint32_t i = 0; i < SWAP_UINT32(prop_length) >> 2; ++i) {
|
||||
uint32_t hex = SWAP_UINT32(*(struct_ptr + 1 + i));
|
||||
@ -175,7 +175,7 @@ void print_fdt() {
|
||||
uart_putc(' ');
|
||||
}
|
||||
} else {
|
||||
// Its a good old string
|
||||
/* Its a good old string */
|
||||
uart_puts((char*)(struct_ptr + 1));
|
||||
}
|
||||
}
|
||||
@ -183,18 +183,17 @@ void print_fdt() {
|
||||
struct_ptr += SWAP_UINT32(prop_length) >> 2;
|
||||
break;
|
||||
|
||||
// End is followed immediately by next token
|
||||
/* End is followed immediately by next token */
|
||||
case FDT_END_NODE:
|
||||
--tab_count;
|
||||
case FDT_NOP:
|
||||
break;
|
||||
|
||||
// There can be only one FDT_END which marks the
|
||||
// end of FDT
|
||||
/* There can be only one FDT_END which marks the end of FDT */
|
||||
case FDT_END:
|
||||
return;
|
||||
}
|
||||
// Advance pointer
|
||||
/* Advance pointer */
|
||||
struct_ptr++;
|
||||
}
|
||||
}
|
||||
|
@ -27,16 +27,16 @@
|
||||
#include <bits/alltypes.h>
|
||||
|
||||
typedef struct fdt_header {
|
||||
uint32_t magic; // Magic value identifying FDT
|
||||
uint32_t totalsize; // Total size of FDT including the header
|
||||
uint32_t off_dt_struct; // Offset from beginning of the FDT to the structure block
|
||||
uint32_t off_dt_strings; // Offset from beginning of the FDT to the strings block
|
||||
uint32_t off_mem_rsvmap; // Offset from beginning of the FDT to the memory reservation map
|
||||
uint32_t version; // FDT version
|
||||
uint32_t last_comp_version; // Last compatible version
|
||||
uint32_t boot_cpuid_phys; // Boot CPU ID
|
||||
uint32_t size_dt_strings; // Size of the strings block
|
||||
uint32_t size_dt_struct; // Size of the structure block
|
||||
uint32_t magic; /* Magic value identifying FDT */
|
||||
uint32_t totalsize; /* Total size of FDT including the header */
|
||||
uint32_t off_dt_struct; /* Offset from beginning of the FDT to the structure block */
|
||||
uint32_t off_dt_strings; /* Offset from beginning of the FDT to the strings block */
|
||||
uint32_t off_mem_rsvmap; /* Offset from beginning of the FDT to the memory reservation map */
|
||||
uint32_t version; /* FDT version */
|
||||
uint32_t last_comp_version; /* Last compatible version */
|
||||
uint32_t boot_cpuid_phys; /* Boot CPU ID */
|
||||
uint32_t size_dt_strings; /* Size of the strings block */
|
||||
uint32_t size_dt_struct; /* Size of the structure block */
|
||||
} fdt_header;
|
||||
|
||||
typedef struct fdt_prop {
|
||||
@ -50,7 +50,7 @@ enum {
|
||||
FDT_END_NODE = 0x2,
|
||||
FDT_PROP = 0x3,
|
||||
FDT_NOP = 0x4,
|
||||
FDT_END = 0x9,
|
||||
FDT_END = 0x9
|
||||
};
|
||||
|
||||
fdt_prop fdt_get_prop(uint32_t*);
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include <uart.h>
|
||||
|
||||
void uart_init() {
|
||||
// Get MMIO, UART and MBOX addresses from FDT
|
||||
/* Get MMIO, UART and MBOX addresses from FDT */
|
||||
fdt_prop ranges = fdt_get_prop(fdt_get_addr("/soc/ranges"));
|
||||
MMIO_BASE = SWAP_UINT32(*ranges.data) - SWAP_UINT32(*(ranges.data+1));
|
||||
|
||||
@ -48,41 +48,41 @@ void uart_init() {
|
||||
UART_IMSC = UART_BASE + 0x38;
|
||||
UART_ICR = UART_BASE + 0x44;
|
||||
|
||||
// Disable UART0.
|
||||
/* Disable UART0. */
|
||||
mmio_write(UART_CR, 0);
|
||||
// Setup the GPIO pin 14 && 15.
|
||||
// Disable pull up/down for all GPIO pins & delay for 150 cycles.
|
||||
/* Setup the GPIO pin 14 && 15.
|
||||
Disable pull up/down for all GPIO pins & delay for 150 cycles. */
|
||||
mmio_write(GPPUD, 0);
|
||||
delay(150);
|
||||
// Disable pull up/down for pin 14,15 & delay for 150 cycles.
|
||||
/* Disable pull up/down for pin 14,15 & delay for 150 cycles. */
|
||||
mmio_write(GPPUDCLK0, (1<<14)|(1<<15));
|
||||
delay(150);
|
||||
// Write 0 to GPPUDCLK0 to make it take effect.
|
||||
/* Write 0 to GPPUDCLK0 to make it take effect. */
|
||||
mmio_write(GPPUDCLK0, 0);
|
||||
// Clear pending interrupts.
|
||||
/* Clear pending interrupts. */
|
||||
mmio_write(UART_ICR, 0x7FF);
|
||||
// Set integer & fractional part of baud rate.
|
||||
// Divider = UART_CLOCK/(16 * Baud)
|
||||
/* Set integer & fractional part of baud rate.
|
||||
Divider = UART_CLOCK/(16 * Baud) */
|
||||
mmio_write(UART_IBRD, 1);
|
||||
// Fractional part register = (.627 * 64) + 0.5 = 40.6 = ~40.
|
||||
/* Fractional part register = (.627 * 64) + 0.5 = 40.6 = ~40. */
|
||||
mmio_write(UART_FBRD, 40);
|
||||
// Enable FIFO & 8 bit data transmission (1 stop bit, no parity).
|
||||
/* Enable FIFO & 8 bit data transmission (1 stop bit, no parity). */
|
||||
mmio_write(UART_LCRH, (1<<4)|(1<<5)|(1<<6));
|
||||
// Mask all interrupts.
|
||||
/* Mask all interrupts. */
|
||||
mmio_write(UART_IMSC, (1<<1)|(1<<4)|(1<<5)|(1<<6)
|
||||
|(1<<7)|(1<<8)|(1<<9)|(1<<10));
|
||||
// Enable UART0, receive & transfer part of UART.
|
||||
/* Enable UART0, receive & transfer part of UART. */
|
||||
mmio_write(UART_CR, 1|(1<<8)|(1<<9));
|
||||
}
|
||||
|
||||
void uart_putc(unsigned char c) {
|
||||
// Wait for UART to become ready to transmit.
|
||||
/* Wait for UART to become ready to transmit. */
|
||||
while(mmio_read(UART_FR) & (1<<5));
|
||||
mmio_write(UART_DR, c);
|
||||
}
|
||||
|
||||
unsigned char uart_getc() {
|
||||
// Wait for UART to have received something.
|
||||
/* Wait for UART to have received something. */
|
||||
while (mmio_read(UART_FR) & (1<<4));
|
||||
return mmio_read(UART_DR);
|
||||
}
|
||||
|
@ -22,15 +22,15 @@
|
||||
#include <sys/cdefs.h>
|
||||
#include <stddef.h>
|
||||
|
||||
char* stpcpy(char* restrict, const char* restrict);
|
||||
char* strcpy(char* restrict, const char* restrict);
|
||||
char* strcat(char* restrict, const char* restrict);
|
||||
char* strtok(char* restrict, const char* restrict);
|
||||
int strcmp(const char* restrict, const char* restrict);
|
||||
char* stpcpy(char* restrict, const char*);
|
||||
char* strcpy(char* restrict, const char*);
|
||||
char* strcat(char* restrict, const char*);
|
||||
char* strtok(char* restrict, const char*);
|
||||
int strcmp(const char* restrict, const char*);
|
||||
char* strchr(const char* restrict, int c);
|
||||
|
||||
int memcmp(const void*, const void*, size_t);
|
||||
void* memcpy(void* restrict, const void* restrict, size_t);
|
||||
void* memcpy(void* restrict, const void*, size_t);
|
||||
void* memmove(void*, const void*, size_t);
|
||||
void* memset(void*, int, size_t);
|
||||
size_t strlen(const char*);
|
||||
|
@ -50,7 +50,7 @@ int printf(const char* restrict format, ...) {
|
||||
amount++;
|
||||
}
|
||||
if (maxrem < amount) {
|
||||
// EOVERFLOW.
|
||||
/* EOVERFLOW */
|
||||
return -1;
|
||||
}
|
||||
if (!print(format, amount)) {
|
||||
@ -71,7 +71,7 @@ int printf(const char* restrict format, ...) {
|
||||
format++;
|
||||
char c = (char)va_arg(params, int);
|
||||
if (!maxrem) {
|
||||
// EOVERFLOW
|
||||
/* EOVERFLOW */
|
||||
return -1;
|
||||
}
|
||||
if (!print(&c, sizeof(c))) {
|
||||
@ -85,7 +85,7 @@ int printf(const char* restrict format, ...) {
|
||||
const char* str = va_arg(params, const char*);
|
||||
len = strlen(str);
|
||||
if (maxrem < len) {
|
||||
// TODO: EOVERFLOW
|
||||
/* TODO: EOVERFLOW */
|
||||
return -1;
|
||||
}
|
||||
if (!print(str, len)) {
|
||||
@ -100,7 +100,7 @@ int printf(const char* restrict format, ...) {
|
||||
itoa(num, buf, 10);
|
||||
len = strlen(buf);
|
||||
if(maxrem < len) {
|
||||
// EOVERFLOW
|
||||
/* EOVERFLOW */
|
||||
return -1;
|
||||
}
|
||||
if(!print(buf, len)) {
|
||||
@ -115,7 +115,7 @@ int printf(const char* restrict format, ...) {
|
||||
uitoa(unum, buf, 16);
|
||||
len = strlen(buf);
|
||||
if(maxrem < len) {
|
||||
// EOVERFLOW
|
||||
/* EOVERFLOW */
|
||||
return -1;
|
||||
}
|
||||
if(!print(buf, len)) {
|
||||
@ -128,7 +128,7 @@ int printf(const char* restrict format, ...) {
|
||||
format = format_begun_at;
|
||||
len = strlen(format);
|
||||
if (maxrem < len) {
|
||||
// EOVERFLOW
|
||||
/* EOVERFLOW */
|
||||
return -1;
|
||||
}
|
||||
if (!print(format, len)) {
|
||||
|
@ -23,25 +23,25 @@
|
||||
#if _ARCH_AARCH64
|
||||
#include <uart.h>
|
||||
#else
|
||||
// TODO: other arch implementation
|
||||
/* TODO: AMD64 implementation */
|
||||
#endif
|
||||
|
||||
#else
|
||||
// TODO: Userspace implementation
|
||||
/* TODO: Userspace implementation */
|
||||
#endif
|
||||
|
||||
int putchar(int ic) {
|
||||
// aarch64 print function
|
||||
/* aarch64 print function */
|
||||
#ifdef _IS_YUKARI
|
||||
|
||||
#if _ARCH_AARCH64
|
||||
uart_putc((char)ic);
|
||||
#else
|
||||
// TODO: other arch implementation
|
||||
/* TODO: AMD64 implementation */
|
||||
#endif
|
||||
|
||||
#else
|
||||
// TODO: Userspace implementation
|
||||
/* TODO: Userspace implementation */
|
||||
#endif
|
||||
|
||||
return ic;
|
||||
|
@ -19,7 +19,7 @@
|
||||
#ifdef _IS_YUKARI
|
||||
#include <hal.h>
|
||||
#else
|
||||
// TODO: Userspace abort implementation
|
||||
/* TODO: Userspace abort implementation */
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
@ -29,7 +29,7 @@ void abort() {
|
||||
printf("kernel panic!!\n");
|
||||
hcf();
|
||||
#else
|
||||
// TODO: Abnormally terminate the process as if by SIGABRT.
|
||||
/* TODO: Abnormally terminate the process as if by SIGABRT. */
|
||||
printf("abort!!\n");
|
||||
#endif
|
||||
for(;;);
|
||||
|
@ -30,14 +30,14 @@ char* itoa(int value, char* buffer, int base) {
|
||||
uint8_t negative = 0;
|
||||
uint8_t digit = 0;
|
||||
|
||||
// Handle negative numbers
|
||||
/* Handle negative numbers */
|
||||
if (value < 0) {
|
||||
negative = 1;
|
||||
value = abs(value);
|
||||
}
|
||||
|
||||
// Put base remainder of value into the buffer
|
||||
// while dividing value by base
|
||||
/* Put base remainder of value into the buffer
|
||||
while dividing value by base */
|
||||
do {
|
||||
digit = value % base;
|
||||
buffer[index] = digits[digit];
|
||||
@ -45,14 +45,14 @@ char* itoa(int value, char* buffer, int base) {
|
||||
value /= base;
|
||||
} while (value);
|
||||
|
||||
// Put negative character in the end
|
||||
/* Put negative character in the end */
|
||||
if(negative) {
|
||||
buffer[index++] = '-';
|
||||
}
|
||||
// Null terminate
|
||||
/* Null terminate */
|
||||
buffer[index] = 0;
|
||||
|
||||
// Reverse the buffer
|
||||
/* Reverse the buffer */
|
||||
uint8_t len = index;
|
||||
char temp = 0;
|
||||
for(uint8_t i = 0; i < len >> 1; ++i) {
|
||||
|
@ -28,8 +28,8 @@ char* uitoa(uint32_t value, char* buffer, int base) {
|
||||
uint8_t index = 0;
|
||||
uint8_t digit = 0;
|
||||
|
||||
// Put base remainder of value into the buffer
|
||||
// while dividing value by base
|
||||
/* Put base remainder of value into the buffer
|
||||
while dividing value by base */
|
||||
do {
|
||||
digit = value % base;
|
||||
buffer[index] = digits[digit];
|
||||
@ -37,10 +37,10 @@ char* uitoa(uint32_t value, char* buffer, int base) {
|
||||
value /= base;
|
||||
} while (value);
|
||||
|
||||
// Null terminate
|
||||
/* Null terminate */
|
||||
buffer[index] = 0;
|
||||
|
||||
// Reverse the buffer
|
||||
/* Reverse the buffer */
|
||||
uint8_t len = index;
|
||||
char temp = 0;
|
||||
for(uint8_t i = 0; i < len >> 1; ++i) {
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void* memcpy(void* restrict dstptr, const void* restrict srcptr, size_t size) {
|
||||
void* memcpy(void* restrict dstptr, const void* srcptr, size_t size) {
|
||||
unsigned char* dst = (unsigned char*) dstptr;
|
||||
const unsigned char* src = (const unsigned char*) srcptr;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
char* stpcpy(char* restrict d, const char* restrict s){
|
||||
char* stpcpy(char* restrict d, const char* s){
|
||||
for(;(*d=*s); s++, d++);
|
||||
return d;
|
||||
}
|
@ -18,7 +18,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
char* strcat(char* restrict dest, const char* restrict src) {
|
||||
char* strcat(char* restrict dest, const char* src) {
|
||||
strcpy(dest + strlen(dest), src);
|
||||
return dest;
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
int strcmp(const char* restrict str1, const char* restrict str2) {
|
||||
int strcmp(const char* restrict str1, const char* str2) {
|
||||
while(*str1 || *str2) {
|
||||
if(*str1 != *str2) return *str1 - *str2;
|
||||
str1++;
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
char* strcpy(char* restrict dest, const char* restrict src) {
|
||||
char* strcpy(char* restrict dest, const char* src) {
|
||||
stpcpy(dest, src);
|
||||
return dest;
|
||||
}
|
@ -18,7 +18,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
char* strtok(char* restrict str, const char* restrict delim) {
|
||||
char* strtok(char* restrict str, const char* delim) {
|
||||
static char* lastToken = 0;
|
||||
|
||||
if(str) {
|
||||
|
@ -18,17 +18,16 @@
|
||||
|
||||
#include <shinobu.h>
|
||||
|
||||
|
||||
EFI_FILE_PROTOCOL* EFIAPI
|
||||
OpenFile(CHAR16 *path) {
|
||||
EFI_STATUS status;
|
||||
|
||||
// Locate handle supporting SFSP
|
||||
/* Locate handle supporting SFSP */
|
||||
EFI_HANDLE *handles;
|
||||
UINTN handleCnt;
|
||||
EFI_GUID sfspGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
|
||||
|
||||
status = uefi_call_wrapper(BS->LocateHandleBuffer, 5,
|
||||
status = uefi_call_wrapper(*(void**)&BS->LocateHandleBuffer, 5,
|
||||
ByProtocol,
|
||||
&sfspGuid,
|
||||
NULL,
|
||||
@ -37,27 +36,27 @@ OpenFile(CHAR16 *path) {
|
||||
);
|
||||
PRINT_ERR(status);
|
||||
|
||||
// TODO: Might need to iterate on all handles if
|
||||
// multiple FAT32 images are connected
|
||||
// Open Filesystem
|
||||
/* TODO: Might need to iterate on all handles if
|
||||
multiple FAT32 images are connected
|
||||
Open Filesystem */
|
||||
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs = NULL;
|
||||
status = uefi_call_wrapper(BS->HandleProtocol, 3,
|
||||
status = uefi_call_wrapper(*(void**)&BS->HandleProtocol, 3,
|
||||
handles[0],
|
||||
&sfspGuid,
|
||||
(VOID**)&fs
|
||||
);
|
||||
PRINT_ERR(status);
|
||||
|
||||
// Open ROOTDIR
|
||||
/* Open ROOTDIR */
|
||||
EFI_FILE_PROTOCOL *root = NULL;
|
||||
status = uefi_call_wrapper(fs->OpenVolume, 2,
|
||||
status = uefi_call_wrapper(*(void**)&fs->OpenVolume, 2,
|
||||
fs,
|
||||
&root
|
||||
);
|
||||
PRINT_ERR(status);
|
||||
|
||||
// Open file
|
||||
status = uefi_call_wrapper(root->Open, 5,
|
||||
/* Open file */
|
||||
status = uefi_call_wrapper(*(void**)&root->Open, 5,
|
||||
root,
|
||||
&root,
|
||||
path,
|
||||
@ -71,15 +70,15 @@ OpenFile(CHAR16 *path) {
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
SetPos(EFI_FILE_PROTOCOL *file, UINTN pos) {
|
||||
return uefi_call_wrapper(file->SetPosition, 2, file, pos);
|
||||
return uefi_call_wrapper(*(void**)&file->SetPosition, 2, file, pos);
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
Read(EFI_FILE_PROTOCOL *file, UINTN *size, VOID *dest) {
|
||||
return uefi_call_wrapper(file->Read, 3, file, size, dest);
|
||||
return uefi_call_wrapper(*(void**)&file->Read, 3, file, size, dest);
|
||||
}
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
Close(EFI_FILE_PROTOCOL *file) {
|
||||
return uefi_call_wrapper(file->Close, 1, file);
|
||||
return uefi_call_wrapper(*(void**)&file->Close, 1, file);
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ EFI_STATUS EFIAPI SetPos(EFI_FILE_PROTOCOL*, UINTN);
|
||||
EFI_STATUS EFIAPI Read(EFI_FILE_PROTOCOL*, UINTN*, VOID*);
|
||||
EFI_STATUS EFIAPI Close(EFI_FILE_PROTOCOL*);
|
||||
|
||||
// elf.h
|
||||
/* elf.h */
|
||||
#define EI_NIDENT (16)
|
||||
typedef uint16_t Elf64_Half;
|
||||
typedef uint32_t Elf64_Word;
|
||||
|
@ -20,16 +20,16 @@
|
||||
|
||||
EFI_STATUS EFIAPI
|
||||
SetMemoryMap(UEFIMemoryMap *map) {
|
||||
// Set a size for memory map
|
||||
/* Set a size for memory map */
|
||||
EFI_STATUS status;
|
||||
map->memoryMapSize = sizeof(EFI_MEMORY_DESCRIPTOR) * 64;
|
||||
|
||||
// Loop until we correctly get a memory map or come across
|
||||
// an error
|
||||
/* Loop until we correctly get a memory map or come across
|
||||
an error */
|
||||
for(;;) {
|
||||
// Try allocating and getting memory map
|
||||
/* Try allocating and getting memory map */
|
||||
map->memoryMap = AllocatePool(map->memoryMapSize);
|
||||
status = uefi_call_wrapper(BS->GetMemoryMap, 5,
|
||||
status = uefi_call_wrapper(*(void**)&BS->GetMemoryMap, 5,
|
||||
&map->memoryMapSize,
|
||||
map->memoryMap,
|
||||
&map->mapKey,
|
||||
@ -37,8 +37,8 @@ SetMemoryMap(UEFIMemoryMap *map) {
|
||||
&map->descriptorVersion
|
||||
);
|
||||
|
||||
// If allocated buffer is too small, free buffer and
|
||||
// increase its size
|
||||
/* If allocated buffer is too small, free buffer and
|
||||
increase its size */
|
||||
if (status == EFI_BUFFER_TOO_SMALL) {
|
||||
FreePool(map->memoryMap);
|
||||
map->memoryMapSize += sizeof(EFI_MEMORY_DESCRIPTOR) * 16;
|
||||
|
@ -22,21 +22,21 @@ EFI_STATUS EFIAPI
|
||||
efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
||||
EFI_STATUS status;
|
||||
|
||||
// Initialize UEFI library
|
||||
/* Initialize UEFI library */
|
||||
InitializeLib(ImageHandle, SystemTable);
|
||||
|
||||
// Store SystemTable and BootServices
|
||||
/* Store SystemTable and BootServices */
|
||||
ST = SystemTable;
|
||||
BS = ST->BootServices;
|
||||
|
||||
// Clear Screen
|
||||
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||
/* Clear Screen */
|
||||
uefi_call_wrapper(*(void**)&ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||
Print(L"Shinobu Bootloader Alpha\n");
|
||||
|
||||
// Open ELF64 Kernel
|
||||
/* Open ELF64 Kernel */
|
||||
EFI_FILE_PROTOCOL *kernelFile = OpenFile(L"yukari");
|
||||
|
||||
// Read ELF Header
|
||||
/* Read ELF Header */
|
||||
UINTN EHeaderSize = sizeof(Elf64_Ehdr);
|
||||
Elf64_Ehdr *kernelElfHeader = AllocatePool(EHeaderSize);
|
||||
|
||||
@ -45,7 +45,7 @@ efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
||||
PRINT_ERR(status);
|
||||
Print(L"ELF Header Loc: 0x%x\n", kernelElfHeader);
|
||||
|
||||
// Read ELF Prog Header
|
||||
/* Read ELF Prog Header */
|
||||
UINTN PHeaderSize = kernelElfHeader->e_phnum * kernelElfHeader->e_phentsize;
|
||||
Elf64_Phdr* kernelProgHeader = AllocatePool(PHeaderSize);
|
||||
|
||||
@ -54,22 +54,22 @@ efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
||||
PRINT_ERR(status);
|
||||
Print(L"ELF Prog Header Loc: 0x%x\n", kernelProgHeader);
|
||||
|
||||
// Load Program Segments
|
||||
/* Load Program Segments */
|
||||
for(UINT16 i = 0; i < kernelElfHeader->e_phnum; ++i) {
|
||||
if(kernelProgHeader[i].p_type == 1) {
|
||||
// Get count of pages needed
|
||||
/* Get count of pages needed */
|
||||
int pages = (kernelProgHeader[i].p_memsz + EFI_PAGE_SIZE - 1) / EFI_PAGE_SIZE;
|
||||
// Get segment address
|
||||
/* Get segment address */
|
||||
Elf64_Addr segment = kernelProgHeader[i].p_paddr;
|
||||
// Allocate pages to the segment address
|
||||
status = uefi_call_wrapper(BS->AllocatePages, 4,
|
||||
/* Allocate pages to the segment address */
|
||||
status = uefi_call_wrapper(*(void**)&BS->AllocatePages, 4,
|
||||
AllocateAddress,
|
||||
EfiLoaderData,
|
||||
pages,
|
||||
&segment
|
||||
);
|
||||
PRINT_ERR(status);
|
||||
// Write program segment to the allocated address
|
||||
/* Write program segment to the allocated address */
|
||||
UINTN fileSize = kernelProgHeader[i].p_filesz;
|
||||
SetPos(kernelFile, kernelProgHeader[i].p_offset);
|
||||
status = Read(kernelFile, &fileSize, (VOID*)segment);
|
||||
@ -78,21 +78,21 @@ efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
||||
}
|
||||
Print(L"Finished reading kernel\nKernel Entry: 0x%x\n", kernelElfHeader->e_entry);
|
||||
|
||||
// Close the kernel file
|
||||
/* Close the kernel file */
|
||||
Close(kernelFile);
|
||||
|
||||
// Set Memory Map and exit boot services
|
||||
/* Set Memory Map and exit boot services */
|
||||
UEFIMemoryMap map;
|
||||
status = SetMemoryMap(&map);
|
||||
uefi_call_wrapper(BS->ExitBootServices, 2,
|
||||
uefi_call_wrapper(*(void**)&BS->ExitBootServices, 2,
|
||||
ImageHandle,
|
||||
map.mapKey
|
||||
);
|
||||
|
||||
// Jump to kernel
|
||||
/* Jump to kernel */
|
||||
VOID (*_start)(VOID) = (VOID (*)(VOID))kernelElfHeader->e_entry;
|
||||
_start();
|
||||
|
||||
// Should be unreachable
|
||||
/* Should be unreachable */
|
||||
return EFI_LOAD_ERROR;
|
||||
}
|
@ -23,7 +23,7 @@
|
||||
#include <fb.h>
|
||||
|
||||
#else
|
||||
//
|
||||
|
||||
#endif
|
||||
|
||||
#include <hal.h>
|
||||
|
Loading…
Reference in New Issue
Block a user