Compare commits

...

2 commits

Author SHA1 Message Date
trimill 85a9443704
formatting 2024-02-03 21:08:36 -05:00
trimill 6b49a206c2
fix lib 2024-02-03 21:05:35 -05:00
15 changed files with 543 additions and 355 deletions

View file

@ -10,7 +10,7 @@ size_t backtrace(void **dst, size_t len);
size_t backtrace_ex(void **dst, size_t len, void *ip, void *bp); size_t backtrace_ex(void **dst, size_t len, void *ip, void *bp);
// Log a backtrace // Log a backtrace
void log_backtrace(); void log_backtrace(void);
// same as log_backtrace with specified insruction and base pointer // same as log_backtrace with specified insruction and base pointer
void log_backtrace_ex(void *ip, void *bp); void log_backtrace_ex(void *ip, void *bp);

View file

@ -1,3 +1,3 @@
#pragma once #pragma once
void enable_fpu(); void enable_fpu(void);

View file

@ -3,60 +3,77 @@
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
/**
* The memcmp() function compares the first n bytes (each interpreted as unsigned char) of the memory //
* areas s1 and s2. // memory operations
*/ //
int memcmp(const void *restrict s1, const void *restrict s2, unsigned long n);
/** /**
* the memcpy() function copies n bytes from memory area src to memory area dest. * Compare the first n bytes (interpreted as unsigned char) of the memory areas s1 and s2
* the memory areas must not overlap. * @param s1 - the first memory area
* @param s2 - the second memory area
* @param n - the byte count
* @returns an interger less than, equal to, or greater than 0 if the first n bytes
* of s1 are less than, equal to, or greater than s2.
*/ */
void *memcpy(void *restrict dest, const void *restrict src, unsigned long n); int memcmp(const void *restrict s1, const void *restrict s2, size_t n);
/** /**
* the memcpy() function copies n bytes from memory area src to memory area dest. * Copy the first n bytes from memory area src to memory area dest. The memory
* the memory areas must not overlap. * areas must not overlap.
* @param dest - the destination
* @param src - the source
* @param n - the byte count
* @returns a pointer to dest
*/ */
volatile void *memcpyv(volatile void *dest, const volatile void *src, unsigned long n); void *memcpy(void *restrict dest, const void *restrict src, size_t n);
/** /**
* The memmove() function copies n bytes from memory area src to memory area dest. The memory areas * Volatile version of memcpy.
* may overlap: copying takes place as though the bytes in src are first copied into a temporary array * Copy the first n bytes from memory area src to memory area dest. The memory
* that does not overlap src or dest, and the bytes are then copied from the temporary array to dest. * areas must not overlap.
* @param dest - the destination
* @param src - the source
* @param n - the byte count
* @returns a pointer to dest
*/ */
void *memmove(void *dest, const void *src, unsigned long n); volatile void *memcpyv(volatile void *restrict dest, const volatile void *restrict src, size_t n);
/** /**
* The memset() function fills the first n bytes of the memory area pointed to by s with the constant * Copy the first n bytes from memory area src to memory area dest. The memory
* byte c. * areas may overlap; memmove behaves as though the bytes are first copied to a
* temporary array.
* @param dest - the destination
* @param src - the source
* @param n - the byte count
* @returns a pointer to dest
*/ */
void *memset(void *restrict dest, int c, unsigned long n); void *memmove(void *dest, const void *src, size_t n);
/** /**
* The memset() function fills the first n bytes of the memory area pointed to by s with the constant * Fill the first n bytes of the memory region dest with the constant byte c.
* byte c. * @param dest - the destination
* @param c - the byte to write
* @param n - the byte count
* @returns a pointer to dest
*/ */
volatile void *memsetv(volatile void *dest, int c, unsigned long n); void *memset(void *dest, int c, size_t n);
/** /**
* The strcmp() function compares the two strings s1 and s2. The locale is not taken into account * Volatile version of memset.
* (for a locale-aware comparison, see strcoll(3)). The comparison is done using unsigned characters. * Fill the first n bytes of the memory region dest with the constant byte c.
* @param c - the byte to write
* @param n - the byte count
* @returns a pointer to dest
*/ */
int strncmp(const char *restrict s1, const char *restrict s2, unsigned long n); volatile void *memsetv(volatile void *dest, int c, size_t n);
/**
* Copys the string pointed to by src , into a string at the buffer pointer to by dest.
* The dest buffer must be long enough to hold src.
*/
char *strcpy(char *restrict dest, const char *restrict src);
/** //
* Copys the string pointed to by src , into a string at the buffer pointer to by dest. // string operations
* The dest buffer must be long enough to hold src or size n. //
*/
char *strncpy(char *restrict dest, const char *restrict src, unsigned long n);
/** /**
* Calculates the length of the string pointed to by str, excluding * Calculates the length of the string pointed to by str, excluding
@ -67,13 +84,75 @@ char *strncpy(char *restrict dest, const char *restrict src, unsigned long n);
size_t strlen(const char *str); size_t strlen(const char *str);
/** /**
* Concatenate the string pointed to by src after the string pointed * Compare at most the first n bytes of the strings s1 and s2. The comparison is
* to by dst. * done using unsigned characters.
* @param dst - the pointer to the destination string * @param s1 - a pointer to the first string
* @param src - the pointer to the source string * @param s2 - a pointer to the second string
* @returns dst * @param n - the maximum number of bytes
* @returns an interger less than, equal to, or greater than 0 if s1 compares less
* than, equal to, or greater than s2
*/ */
char *strcat(char *restrict dst, const char *restrict src); int strncmp(const char *restrict s1, const char *restrict s2, size_t n);
//
// string copying and concatenation
//
/**
* Copies the string pointed to by src into the buffer pointer to by dest.
* The dest buffer must be long enough to hold src.
* @param dest - the destination
* @param src - the source
* @returns a pointer to dest
*/
char *strcpy(char *restrict dest, const char *restrict src);
/**
* Copies the string pointed to by src into the buffer pointer to by dest.
* The dest buffer must be long enough to hold src or size n.
* @param dest - the destination
* @param src - the source
* @param n - the maximum number of bytes
* @returns a pointer to dest
*/
char *strncpy(char *restrict dest, const char *restrict src, size_t n);
/**
* Copies the string pointed to by src into the buffer pointed to by dest.
* The dest buffer must be long enough to hold src.
* @param dest - the destination
* @param src - the source
* @param n - the maximum number of bytes
* @returns a pointer to the terminating null byte
*/
char *stpcpy(char *restrict dest, const char *restrict src);
/**
* Copies the string pointed to by src into the buffer pointed to by dest.
* The dest buffer must be long enough to hold src or size n.
* @param dest - the destination
* @param src - the source
* @param n - the maximum number of bytes
* @returns a pointer to the byte after the last character copied
*/
char *stpncpy(char *restrict dest, const char *restrict src, size_t n);
/**
* Concatenate the string pointed to by src after the string pointed
* to by dest.
* @param dest - the destination
* @param src - the source
* @returns a pointer to dest
*/
char *strcat(char *restrict dest, const char *restrict src);
//
// character operations
//
/** /**
* @returns 1 if c is a space * @returns 1 if c is a space
@ -95,10 +174,16 @@ char itoc(int i);
/** /**
* converts single base 36 chat into int * converts single base 36 chat into int
* @param c - base 36 char * @param c - base 36 char
* @returns i - int * @returns i - int, or -1 if the char was invalid
*/ */
int ctoi(char c); int ctoi(char c);
//
// string/numeric conversions
//
/** /**
* Converts the initial portiion of the string pointed to by s to int. * Converts the initial portiion of the string pointed to by s to int.
* @param s - the string to convert * @param s - the string to convert
@ -168,14 +253,6 @@ char *ultoa(unsigned long int n, char *buffer, int radix);
*/ */
char *ulltoa(unsigned long long int n, char *buffer, int radix); char *ulltoa(unsigned long long int n, char *buffer, int radix);
/**
* Converts a byte count to a human readable file size
* @param bytes - the bytes to convert
* @param buf - the buffer to store it in
* @preturns - bus
*/
char *btoa(size_t bytes, char *buf);
/** /**
* Converts the string in str to an int value based on the given base. * Converts the string in str to an int value based on the given base.
* The endptr is updated to where the string was no longer valid. * The endptr is updated to where the string was no longer valid.
@ -187,7 +264,7 @@ char *btoa(size_t bytes, char *buf);
int strtoi(const char *str, char **endptr, int base); int strtoi(const char *str, char **endptr, int base);
/** /**
* Converts the string in str to an long value based on the given base. * Converts the string in str to a long value based on the given base.
* The endptr is updated to where the string was no longer valid. * The endptr is updated to where the string was no longer valid.
* @param str - the string buffer * @param str - the string buffer
* @param endptr - the endptr * @param endptr - the endptr
@ -197,7 +274,7 @@ int strtoi(const char *str, char **endptr, int base);
long int strtol(const char *str, char **endptr, int base); long int strtol(const char *str, char **endptr, int base);
/** /**
* Converts the string in str to an long long value based on the given base. * Converts the string in str to a long long value based on the given base.
* The endptr is updated to where the string was no longer valid. * The endptr is updated to where the string was no longer valid.
* @param str - the string buffer * @param str - the string buffer
* @param endptr - the endptr * @param endptr - the endptr
@ -206,6 +283,61 @@ long int strtol(const char *str, char **endptr, int base);
*/ */
long long int strtoll(const char *str, char **endptr, int base); long long int strtoll(const char *str, char **endptr, int base);
/**
* Converts the string in str to an unsigned int value based on the given base.
* The endptr is updated to where the string was no longer valid.
* @param str - the string buffer
* @param endptr - the endptr
* @param base - the base to convert to
* @returns 0 on error or success, error if endptr is still equal to str
*/
unsigned int strtoui(const char *str, char **endptr, int base);
/**
* Converts the string in str to an unsigned long value based on the given base.
* The endptr is updated to where the string was no longer valid.
* @param str - the string buffer
* @param endptr - the endptr
* @param base - the base to convert to
* @returns 0 on error or success, error if endptr is still equal to str
*/
unsigned long int strtoul(const char *str, char **endptr, int base);
/**
* Converts the string in str to an unsigned long long value based on the given base.
* The endptr is updated to where the string was no longer valid.
* @param str - the string buffer
* @param endptr - the endptr
* @param base - the base to convert to
* @returns 0 on error or success, error if endptr is still equal to str
*/
unsigned long long int strtoull(const char *str, char **endptr, int base);
/**
* Converts a byte count to a human readable file size of at most four characters
* using binary suffixes.
*
* The following rules are applied:
* - If the byte count is less than 1024, the count is written in decimal
* and no suffix is applied
* - Otherwise, repeatedly divide by 1024 until the value is under 1000.
* - If the value has two or three decimal digits, print it followed by the
* approprate suffix.
* - If the value has one decimal digit, print it along with a single fractional
* digit. This also applies if the value is zero.
*
* @param bytes - the bytes to convert
* @param buf - a pointer to the buffer to store it in (which must be at least five
* bytes long)
* @returns - buf
*/
char *btoa(size_t bytes, char *buf);
//
// printing and formatting
//
/** /**
* Prints out a char * Prints out a char
* @param c - the char * @param c - the char

View file

@ -4,7 +4,7 @@
#define _PANIC_STR2(x) #x #define _PANIC_STR2(x) #x
#define panic(...) _panic_impl(_PANIC_STR(__LINE__), __FILE__, __VA_ARGS__) #define panic(...) _panic_impl(_PANIC_STR(__LINE__), __FILE__, __VA_ARGS__)
#define kassert(val, ...) do { if (!(val)) { panic(__VA_ARGS__); } } while(0) #define kassert(val, ...) do { if (!(val)) { panic(__VA_ARGS__); } } while (0)
__attribute__((format(printf, 3, 4))) __attribute__((format(printf, 3, 4)))
_Noreturn void _panic_impl(char *line, char *file, char *format, ...); _Noreturn void _panic_impl(char *line, char *file, char *format, ...);

View file

@ -26,7 +26,7 @@ size_t backtrace_ex(void **dst, size_t len, void *ip, void *bp) {
return i; return i;
} }
void log_backtrace() { void log_backtrace(void) {
struct stackframe *rbp; struct stackframe *rbp;
__asm__ ("mov %%rbp, %0" : "=r"(rbp)); __asm__ ("mov %%rbp, %0" : "=r"(rbp));
log_backtrace_ex(rbp->rip, rbp->rbp); log_backtrace_ex(rbp->rip, rbp->rbp);

View file

@ -8,64 +8,64 @@
struct dr6 { struct dr6 {
uint64_t b0 : 1, uint64_t b0 : 1,
b1 : 1, b1 : 1,
b2 : 1, b2 : 1,
b3 : 1, b3 : 1,
: 7, : 7,
bld : 1, bld : 1,
: 1, : 1,
bd : 1, bd : 1,
bs : 1, bs : 1,
bt : 1, bt : 1,
rtm : 1, rtm : 1,
: 47; : 47;
}; };
struct dr7 { struct dr7 {
uint64_t l0 : 1, uint64_t l0 : 1,
g0 : 1, g0 : 1,
l1 : 1, l1 : 1,
g1 : 1, g1 : 1,
l2 : 1, l2 : 1,
g2 : 1, g2 : 1,
l3 : 1, l3 : 1,
g3 : 1, g3 : 1,
: 8, : 8,
rw0 : 2, rw0 : 2,
len0 : 2, len0 : 2,
rw1 : 2, rw1 : 2,
len1 : 2, len1 : 2,
rw2 : 2, rw2 : 2,
len2 : 2, len2 : 2,
rw3 : 2, rw3 : 2,
len3 : 2, len3 : 2,
: 32; : 32;
}; };
struct rflags { struct rflags {
uint64_t cf : 1, uint64_t cf : 1,
: 1, : 1,
pf : 1, pf : 1,
: 1, : 1,
af : 1, af : 1,
: 1, : 1,
zf : 1, zf : 1,
sf : 1, sf : 1,
tf : 1, tf : 1,
if_ : 1, if_ : 1,
df : 1, df : 1,
of : 1, of : 1,
iopl : 2, iopl : 2,
nt : 1, nt : 1,
md : 1, md : 1,
rf : 1, rf : 1,
vm : 1, vm : 1,
ac : 1, ac : 1,
vif : 1, vif : 1,
vip : 1, vip : 1,
id : 1, id : 1,
: 42; : 42;
}; };
struct breakpoint { struct breakpoint {
@ -103,7 +103,7 @@ static size_t debugger_read(char *buf, size_t len) {
end: end:
result = p - buf; result = p - buf;
kputc('\n'); kputc('\n');
for(; p < buf + len; p++) { for (; p < buf + len; p++) {
*p = 0; *p = 0;
} }
return result; return result;
@ -161,24 +161,24 @@ static void debugger_print_regs(struct isr_regs *state) {
kprintf("rflags: %#016lx (%lu)\n", state->rflags, state->rflags); kprintf("rflags: %#016lx (%lu)\n", state->rflags, state->rflags);
struct rflags *rflags = (struct rflags *)state->rflags; struct rflags *rflags = (struct rflags *)state->rflags;
kputs("rflags: "); kputs("rflags: ");
if(rflags->cf) kputs("CF "); if (rflags->cf) kputs("CF ");
if(rflags->pf) kputs("PF "); if (rflags->pf) kputs("PF ");
if(rflags->af) kputs("AF "); if (rflags->af) kputs("AF ");
if(rflags->zf) kputs("ZF "); if (rflags->zf) kputs("ZF ");
if(rflags->sf) kputs("SF "); if (rflags->sf) kputs("SF ");
if(rflags->tf) kputs("TF "); if (rflags->tf) kputs("TF ");
if(rflags->if_) kputs("IF "); if (rflags->if_) kputs("IF ");
if(rflags->df) kputs("DF "); if (rflags->df) kputs("DF ");
if(rflags->of) kputs("OF "); if (rflags->of) kputs("OF ");
if(rflags->iopl) kputs("IOPL "); if (rflags->iopl) kputs("IOPL ");
if(rflags->nt) kputs("NT "); if (rflags->nt) kputs("NT ");
if(rflags->md) kputs("MD "); if (rflags->md) kputs("MD ");
if(rflags->rf) kputs("RF "); if (rflags->rf) kputs("RF ");
if(rflags->vm) kputs("VM "); if (rflags->vm) kputs("VM ");
if(rflags->ac) kputs("AC "); if (rflags->ac) kputs("AC ");
if(rflags->vif) kputs("VIF "); if (rflags->vif) kputs("VIF ");
if(rflags->vip) kputs("VIP "); if (rflags->vip) kputs("VIP ");
if(rflags->id) kputs("ID "); if (rflags->id) kputs("ID ");
kputs("\n"); kputs("\n");
} }
@ -189,7 +189,7 @@ static int debugger_handle_bkp_cmd(char *msg) {
// list breakpoints // list breakpoints
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
struct breakpoint bkp = bkps[i]; struct breakpoint bkp = bkps[i];
if(!bkp.used) { if (!bkp.used) {
kprintf("breakpoint %d: unset\n", i); kprintf("breakpoint %d: unset\n", i);
continue; continue;
} }
@ -278,7 +278,7 @@ static int debugger_handle_bkp_cmd(char *msg) {
} }
} }
static void debugger_load_bkps() { static void debugger_load_bkps(void) {
struct dr7 dr7; struct dr7 dr7;
__asm__ volatile ("mov %%dr7, %0" : "=r"(dr7)); __asm__ volatile ("mov %%dr7, %0" : "=r"(dr7));
dr7.g0 = bkps[0].enable & bkps[0].used; dr7.g0 = bkps[0].enable & bkps[0].used;

View file

@ -26,4 +26,4 @@ struct isr_regs {
uint64_t ss; uint64_t ss;
}; };
void idt_init(); void idt_init(void);

View file

@ -30,44 +30,44 @@
#define BOCHS_PCI_DEVICE 0x1111 #define BOCHS_PCI_DEVICE 0x1111
static void write(uint16_t index, uint16_t data) { static void write(uint16_t index, uint16_t data) {
outw(INDEX, index); outw(INDEX, index);
outw(DATA, data); outw(DATA, data);
} }
static uint16_t read(uint16_t value) { static uint16_t read(uint16_t value) {
outw(INDEX, value); outw(INDEX, value);
return inw(DATA); return inw(DATA);
} }
static int is_available(void) { static int is_available(void) {
return (read(INDEX_ID) == 0xB0C5); return (read(INDEX_ID) == 0xB0C5);
} }
static void set_mode(uint16_t width, uint16_t height, uint16_t bit_depth, int lfb, int clear) { static void set_mode(uint16_t width, uint16_t height, uint16_t bit_depth, int lfb, int clear) {
write(INDEX_ENABLE, DATA_DISP_DISABLE); write(INDEX_ENABLE, DATA_DISP_DISABLE);
write(INDEX_XRES, width); write(INDEX_XRES, width);
write(INDEX_YRES, height); write(INDEX_YRES, height);
write(INDEX_BPP, bit_depth); write(INDEX_BPP, bit_depth);
write(INDEX_ENABLE, DATA_DISP_ENABLE | write(INDEX_ENABLE, DATA_DISP_ENABLE |
(lfb ? DATA_LFB_ENABLE : 0) | (lfb ? DATA_LFB_ENABLE : 0) |
(clear ? 0 : DATA_NO_CLEAR_MEM)); (clear ? 0 : DATA_NO_CLEAR_MEM));
} }
volatile uint32_t* bochs_init(uint16_t width, uint16_t height, uint8_t bit_depth) { volatile uint32_t *bochs_init(uint16_t width, uint16_t height, uint8_t bit_depth) {
set_mode(width, height, bit_depth, true, true); set_mode(width, height, bit_depth, true, true);
if (!is_available()) if (!is_available())
return NULL; return NULL;
struct pci_device bochs = {0}; struct pci_device bochs = {0};
bool found = pci_findby_id(&bochs, BOCHS_PCI_DEVICE, BOCHS_PCI_VENDOR, NULL); bool found = pci_findby_id(&bochs, BOCHS_PCI_DEVICE, BOCHS_PCI_VENDOR, NULL);
if (!found) if (!found)
return NULL; return NULL;
uint32_t bar0 = pci_rcfg_d(bochs, PCI_BAR0_D); uint32_t bar0 = pci_rcfg_d(bochs, PCI_BAR0_D);
uint32_t *addr = (uint32_t*) (uintptr_t) bar0; uint32_t *addr = (uint32_t *) (uintptr_t) bar0;
addr = mmap(addr, width * height * bit_depth); addr = mmap(addr, width * height * bit_depth);
return addr; return addr;
} }

View file

@ -88,7 +88,7 @@ static void print_device(struct pci_table_entry *entry) {
} }
static struct pci_table_entry *load_device(struct pci_device dev) { static struct pci_table_entry *load_device(struct pci_device dev) {
if(pci_table_next >= TABLE_LEN) panic("Too many PCI devices: limit is %d", TABLE_LEN); if (pci_table_next >= TABLE_LEN) panic("Too many PCI devices: limit is %d", TABLE_LEN);
struct pci_table_entry *entry = &pci_table[pci_table_next++]; struct pci_table_entry *entry = &pci_table[pci_table_next++];
entry->device = dev; entry->device = dev;
uint32_t dword0 = pci_rcfg_d(dev, 0); uint32_t dword0 = pci_rcfg_d(dev, 0);
@ -108,25 +108,25 @@ static struct pci_table_entry *load_device(struct pci_device dev) {
void pci_init(void) { void pci_init(void) {
pci_table_next = 0; pci_table_next = 0;
struct pci_device pcidev; struct pci_device pcidev;
for(int bus = 0; bus < 256; bus++) { for (int bus = 0; bus < 256; bus++) {
pcidev.bus = bus; pcidev.bus = bus;
for(int dev = 0; dev < 32; dev++) { for (int dev = 0; dev < 32; dev++) {
pcidev.device = dev; pcidev.device = dev;
pcidev.function = 0; pcidev.function = 0;
uint16_t vendor = pci_rcfg_w(pcidev, 0); uint16_t vendor = pci_rcfg_w(pcidev, 0);
if(vendor == 0xFFFF) continue; if (vendor == 0xFFFF) continue;
load_device(pcidev); load_device(pcidev);
uint8_t header_type = pci_rcfg_b(pcidev, 14); uint8_t header_type = pci_rcfg_b(pcidev, 14);
if(!(header_type & 0x80)) continue; if (!(header_type & 0x80)) continue;
for(int func = 1; func < 8; func++) { for (int func = 1; func < 8; func++) {
pcidev.function = func; pcidev.function = func;
uint16_t vendor = pci_rcfg_w(pcidev, 0); uint16_t vendor = pci_rcfg_w(pcidev, 0);
if(vendor == 0xFFFF) continue; if (vendor == 0xFFFF) continue;
load_device(pcidev); load_device(pcidev);
} }
@ -141,10 +141,10 @@ void pci_init(void) {
bool pci_findby_class(struct pci_device *dest, uint8_t class, uint8_t subclass, size_t *offset) { bool pci_findby_class(struct pci_device *dest, uint8_t class, uint8_t subclass, size_t *offset) {
size_t o = 0; size_t o = 0;
if(offset == NULL) offset = &o; if (offset == NULL) offset = &o;
for(; *offset < pci_table_next; (*offset)++) { for (; *offset < pci_table_next; (*offset)++) {
struct pci_table_entry *entry = &pci_table[*offset]; struct pci_table_entry *entry = &pci_table[*offset];
if(entry->class == class && entry->subclass == subclass) { if (entry->class == class && entry->subclass == subclass) {
*dest = entry->device; *dest = entry->device;
return true; return true;
} }
@ -154,10 +154,10 @@ bool pci_findby_class(struct pci_device *dest, uint8_t class, uint8_t subclass,
bool pci_findby_id(struct pci_device *dest, uint16_t device, uint16_t vendor, size_t *offset) { bool pci_findby_id(struct pci_device *dest, uint16_t device, uint16_t vendor, size_t *offset) {
size_t o = 0; size_t o = 0;
if(offset == NULL) offset = &o; if (offset == NULL) offset = &o;
for(; *offset < pci_table_next; (*offset)++) { for (; *offset < pci_table_next; (*offset)++) {
struct pci_table_entry *entry = &pci_table[*offset]; struct pci_table_entry *entry = &pci_table[*offset];
if(entry->device_id == device && entry->vendor_id == vendor) { if (entry->device_id == device && entry->vendor_id == vendor) {
*dest = entry->device; *dest = entry->device;
return true; return true;
} }

View file

@ -3,7 +3,7 @@
#include <stdint.h> #include <stdint.h>
#include <lib.h> #include <lib.h>
void enable_fpu() { void enable_fpu(void) {
size_t cr4; size_t cr4;
uint16_t cw = 0x37F; uint16_t cw = 0x37F;
__asm__ volatile ("mov %%cr4, %0" : "=r"(cr4)); __asm__ volatile ("mov %%cr4, %0" : "=r"(cr4));

View file

@ -84,15 +84,15 @@ struct mboot_tag_cmdline {
}; };
struct mboot_tag_framebuffer { struct mboot_tag_framebuffer {
uint32_t type; uint32_t type;
uint32_t size; uint32_t size;
uint64_t framebuffer_addr; uint64_t framebuffer_addr;
uint32_t framebuffer_pitch; uint32_t framebuffer_pitch;
uint32_t framebuffer_width; uint32_t framebuffer_width;
uint32_t framebuffer_height; uint32_t framebuffer_height;
uint8_t framebuffer_bpp; uint8_t framebuffer_bpp;
uint8_t framebuffer_type; uint8_t framebuffer_type;
uint16_t reserved; uint16_t reserved;
}; };
static void read_symbols( static void read_symbols(
@ -174,7 +174,7 @@ static void read_memory_map(
uintptr_t i = (uintptr_t)map->entries; uintptr_t i = (uintptr_t)map->entries;
kprintf("MEMORY MAP\n"); kprintf("MEMORY MAP\n");
char buf[20]; char buf[20];
for ( ; for (;
i < (uintptr_t)map->entries + map->size; i < (uintptr_t)map->entries + map->size;
i += map->entry_size, idx++ i += map->entry_size, idx++
) { ) {

412
src/lib.c
View file

@ -2,27 +2,31 @@
#include <lib.h> #include <lib.h>
#include <stddef.h> #include <stddef.h>
int memcmp(const void *restrict vl, const void *restrict vr, unsigned long n) { //
// memory operations
//
int memcmp(const void *restrict vl, const void *restrict vr, size_t n) {
const unsigned char *l = vl, *r = vr; const unsigned char *l = vl, *r = vr;
for (; n && *l == *r; n--, l++, r++); for (; n && *l == *r; n--, l++, r++);
return n ? *l-*r : 0; return n ? *l-*r : 0;
} }
void *memcpy(void *restrict dest, const void *restrict src, unsigned long n) { void *memcpy(void *restrict dest, const void *restrict src, size_t n) {
char *d = dest; char *d = dest;
const char *s = src; const char *s = src;
for (; n; n--) *d++ = *s++; for (; n; n--) *d++ = *s++;
return dest; return dest;
} }
volatile void *memcpyv(volatile void *dest, const volatile void *src, unsigned long n) { volatile void *memcpyv(volatile void *restrict dest, const volatile void *restrict src, size_t n) {
volatile char *d = dest; volatile char *d = dest;
const volatile char *s = src; const volatile char *s = src;
for (; n; n--) *d++ = *s++; for (; n; n--) *d++ = *s++;
return dest; return dest;
} }
void *memmove(void *dest, const void *src, unsigned long n) { void *memmove(void *dest, const void *src, size_t n) {
char *d = dest; char *d = dest;
const char *s = src; const char *s = src;
@ -37,7 +41,7 @@ void *memmove(void *dest, const void *src, unsigned long n) {
return dest; return dest;
} }
void *memset(void *restrict dest, int c, unsigned long n) { void *memset(void *dest, int c, size_t n) {
unsigned char *d = dest; unsigned char *d = dest;
for (; n; n--) { for (; n; n--) {
*d++ = c; *d++ = c;
@ -45,7 +49,7 @@ void *memset(void *restrict dest, int c, unsigned long n) {
return dest; return dest;
} }
volatile void *memsetv(volatile void *dest, int c, unsigned long n) { volatile void *memsetv(volatile void *dest, int c, size_t n) {
volatile unsigned char *d = dest; volatile unsigned char *d = dest;
for (; n; n--) { for (; n; n--) {
*d++ = c; *d++ = c;
@ -53,37 +57,62 @@ volatile void *memsetv(volatile void *dest, int c, unsigned long n) {
return dest; return dest;
} }
int strncmp(const char *restrict lhs, const char *restrict rhs, unsigned long n) { //
// string operations
//
int strncmp(const char *restrict lhs, const char *restrict rhs, size_t n) {
const unsigned char *l=(void *)lhs, *r=(void *)rhs; const unsigned char *l=(void *)lhs, *r=(void *)rhs;
if (!n--) return 0; if (!n--) return 0;
for (; *l && *r && n && *l == *r ; l++, r++, n--); for (; *l && *r && n && *l == *r ; l++, r++, n--);
return *l - *r; return *l - *r;
} }
char *strcpy(char *restrict dest, const char *restrict src) {
char *d = dest;
for (; (*d = *src); d++, src++);
return dest;
}
char *strncpy(char *restrict dest, const char *restrict src, unsigned long n) {
char *d = dest;
for (; (*d = *src) && n; d++, src++, n--);
memset(d, 0, n);
return dest;
}
size_t strlen(const char *str) { size_t strlen(const char *str) {
const char *p; const char *p;
for (p = str; *p != 0; p++) {} for (p = str; *p != 0; p++) {}
return p - str; return p - str;
} }
char *strcat(char *restrict dst, const char *restrict src) { //
strcpy(dst + strlen(dst), src); // string copying and concatenation
return dst; //
char *stpcpy(char *restrict dest, const char *restrict src) {
char *d = dest;
for (; (*d = *src); d++, src++);
return d;
} }
char *stpncpy(char *restrict dest, const char *restrict src, size_t n) {
char *d = dest;
for (; (*d = *src) && n; d++, src++, n--);
memset(d, 0, n);
return d;
}
char *strcpy(char *restrict dest, const char *restrict src) {
char *d = dest;
for (; (*d = *src); d++, src++);
return dest;
}
char *strncpy(char *restrict dest, const char *restrict src, size_t n) {
char *d = dest;
for (; (*d = *src) && n; d++, src++, n--);
memset(d, 0, n);
return dest;
}
char *strcat(char *restrict dest, const char *restrict src) {
strcpy(dest + strlen(dest), src);
return dest;
}
//
// character operations
//
int isspace(int c) { int isspace(int c) {
switch (c) { switch (c) {
case ' ': case ' ':
@ -99,9 +128,12 @@ int isspace(int c) {
} }
int isdigit(int c) { int isdigit(int c) {
return c - '0' > -1 && c - '0' < 10; return c >= '0' && c <= '9';
} }
//
// string/numeric conversions
//
#define ATOX(name, type) \ #define ATOX(name, type) \
type name(const char *s) { \ type name(const char *s) { \
@ -110,7 +142,7 @@ int isdigit(int c) {
switch (*s) { \ switch (*s) { \
case '-': \ case '-': \
neg = 1; \ neg = 1; \
/* FALLTHRU */ \ /* fallthrough */ \
case '+': \ case '+': \
s++; \ s++; \
break; \ break; \
@ -137,181 +169,205 @@ char itoc(int i) {
} }
int ctoi(char c) { int ctoi(char c) {
if (c < 'A') { if (c >= '0' && c <= '9') {
return c - '0'; return c - '0';
} else if (c < 'a') { } else if (c >= 'A' && c <= 'Z') {
return c - 'A' + 10; return c - 'A' + 10;
} else { } else if (c >= 'a' && c <= 'z') {
return c - 'a' + 10; return c - 'a' + 10;
} else {
return -1;
} }
} }
static char fs_endings[] = {'K', 'M', 'G', 'T', 'P'};
static size_t nth_pow(size_t i, size_t e) { #define UXTOA(type, name) \
size_t a = i;
while(--e)
a *= i;
return a;
}
static char nth_digit(size_t bytes, size_t place) {
while (1) {
if (bytes < nth_pow(10, place))
break;
bytes /= 10;
}
return bytes %= 10;
}
char *btoa(const size_t bytes, char *buf) {
char *start = buf;
int idx = -1;
size_t b = bytes;
size_t s = b;
while (1) {
if (b < 1000)
break;
s = b;
b /= 1024;
idx++;
}
if (idx == -1) {
ultoa(bytes, buf, 10);
return start;
}
s = s * 1000 / 1024;
if (s < 1024) {
b = 1024;
idx--;
}
char fd = nth_digit(s, 1);
char sd = nth_digit(s, 2);
char td = nth_digit(s, 3);
*buf = fd + '0';
buf++;
if (b < 10) {
*buf = '.';
buf++;
}
*buf = sd + '0';
buf++;
if (b < 10)
goto end;
if (b > 99) {
*buf = td + '0';
buf++;
}
end:
*buf = fs_endings[idx];
buf++;
*buf = '\0';
return start;
}
#define UXTOA(type, name) \
char *name(unsigned type n, char *buffer, int radix) { \ char *name(unsigned type n, char *buffer, int radix) { \
if (n == 0) { \ if (n == 0) { \
buffer[0] = '0'; \ buffer[0] = '0'; \
buffer[1] = '\0'; \ buffer[1] = '\0'; \
return buffer + 1; \ return buffer + 1; \
} \ } \
char *start = buffer; \ char *start = buffer; \
for (; n; n /= radix) { \ for (; n; n /= radix) { \
*buffer++ = itoc(n % radix); \ *buffer++ = itoc(n % radix); \
} \ } \
char *buf_end = buffer; \ char *buf_end = buffer; \
*buffer-- = '\0'; \ *buffer-- = '\0'; \
while (buffer > start) { \ while (buffer > start) { \
char tmp = *start; \ char tmp = *start; \
*start++ = *buffer; \ *start++ = *buffer; \
*buffer-- = tmp; \ *buffer-- = tmp; \
} \ } \
return buf_end; \ return buf_end; \
} }
UXTOA(int, utoa) UXTOA(int, utoa)
UXTOA(long int, ultoa) UXTOA(long int, ultoa)
UXTOA(long long int, ulltoa) UXTOA(long long int, ulltoa)
#define XTOA(type, name) \ #define XTOA(type, name) \
char *name(type n, char *buffer, int radix) { \ char *name(type n, char *buffer, int radix) { \
if (n == 0) { \ if (n == 0) { \
buffer[0] = '0'; \ buffer[0] = '0'; \
buffer[1] = '\0'; \ buffer[1] = '\0'; \
return buffer + 1; \ return buffer + 1; \
} \ } \
if (n < 0) { \ if (n < 0) { \
*buffer++ = '-'; \ *buffer++ = '-'; \
n = -n; \ n = -n; \
} \ } \
char *start = buffer; \ char *start = buffer; \
for (; n; n /= radix) { \ for (; n; n /= radix) { \
*buffer++ = itoc(n % radix); \ *buffer++ = itoc(n % radix); \
} \ } \
char *buf_end = buffer; \ char *buf_end = buffer; \
*buffer-- = '\0'; \ *buffer-- = '\0'; \
while (buffer > start) { \ while (buffer > start) { \
char tmp = *start; \ char tmp = *start; \
*start++ = *buffer; \ *start++ = *buffer; \
*buffer-- = tmp; \ *buffer-- = tmp; \
} \ } \
return buf_end; \ return buf_end; \
} }
XTOA(int, itoa) XTOA(int, itoa)
XTOA(long int, ltoa) XTOA(long int, ltoa)
XTOA(long long int, lltoa) XTOA(long long int, lltoa)
#define STRTOX(name, type) \ #define STRTOX(name, type) \
type name(const char *s, char **endptr, int radix) { \ type name( \
*endptr = NULL; \ const char *restrict s, \
for (; isspace(*s); s++); \ char **restrict endptr, \
int neg = 0; \ int radix \
switch (*s) { \ ) { \
case '-': \ const char *s_start = s; \
neg = 1; \ for (; isspace(*s); s++); \
/* FALLTHRU */ \ \
case '+': \ int sign = 0; \
s++; \ switch (*s) { \
break; \ case '-': sign = 1; /* fallthrough */ \
} \ case '+': s++; break; \
if (!radix) { \ } \
if (*s == '0') { \ \
s++; \ if ( \
if (*s == 'x' || *s == 'X') { \ (radix == 0 || radix == 16) \
s++; \ && (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) \
radix = 16; \ ) { \
} else { \ radix = 16; \
radix = 8; \ s += 2; \
} \ } else if (radix == 0) { \
} else { \ if (*s == '0') { \
radix = 10; \ radix = 8; \
} \ s++; \
} \ } else { \
for (; *s == '0'; s++, *endptr = (void *) s); \ radix = 10; \
type num = 0; \ } \
for (; isdigit(*s); s++, *endptr = (void *) s) { \ } \
num *= radix; \ \
num += *s - '0'; \ type num = 0; \
} \ int has_digit = 0; \
return num * (neg ? -1 : 1); \ \
while (1) { \
int n = ctoi(*s++); \
if (n < 0 || n >= radix) break; \
has_digit = 1; \
num = num * radix + n; \
} \
\
if (endptr != NULL) { \
*endptr = has_digit ? (char *)(s - 1) : (char *)s_start; \
} \
\
return sign ? -num : num; \
} }
STRTOX(strtoi, int) STRTOX(strtoi, int)
STRTOX(strtol, long int) STRTOX(strtol, long int)
STRTOX(strtoll, long long int) STRTOX(strtoll, long long int)
#define STRTOUX(name, type) \
type name( \
const char *restrict s, \
char **restrict endptr, \
int radix \
) { \
const char *s_start = s; \
for (; isspace(*s); s++); \
\
if ( \
(radix == 0 || radix == 16) \
&& (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) \
) { \
radix = 16; \
s += 2; \
} else if (radix == 0) { \
if (*s == '0') { \
radix = 8; \
s++; \
} else { \
radix = 10; \
} \
} \
\
type num = 0; \
int has_digit = 0; \
\
while (1) { \
int n = ctoi(*s++); \
if (n < 0 || n >= radix) break; \
has_digit = 1; \
num = num * radix + n; \
} \
\
if (endptr != NULL) { \
*endptr = has_digit ? (char *)(s - 1) : (char *)s_start; \
} \
\
return num; \
}
STRTOUX(strtoui, unsigned int)
STRTOUX(strtoul, unsigned long int)
STRTOUX(strtoull, unsigned long long int)
static char suffixes[] = {'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q'};
char *btoa(size_t bytes, char *buf) {
// no suffix if under 1K, print up to four digits
if (bytes < 1024) {
ultoa(bytes, buf, 10);
return buf;
}
// store one digit of remainder for decimal
unsigned int remainder;
// power of 1024
int power = 0;
// iterate until remaining bytes fits in three digits
while (bytes >= 1000) {
remainder = (bytes % 1024) * 10 / 1024;
bytes /= 1024;
power += 1;
}
// end of number
char *end;
if (bytes >= 10) {
// no decimal
end = ultoa(bytes, buf, 10);
} else {
// decimal
end = ultoa(bytes, buf, 10);
end[0] = '.';
end = ultoa(remainder, end + 1, 10);
}
// add suffix
end[0] = suffixes[power - 1];
end[1] = '\0';
return buf;
}

View file

@ -8,9 +8,9 @@
struct page_header { struct page_header {
struct page_header *next; struct page_header *next;
struct page_header *prev; struct page_header *prev;
size_t node_number; // all headers on the same page alloc have the same node number (so they can be merged) size_t node_number; // all headers on the same page alloc have the same node number (so they can be merged)
size_t free; // free space after the node (if its the last node in the alloc block) size_t free; // free space after the node (if its the last node in the alloc block)
size_t used; // how much space this allocation is using size_t used; // how much space this allocation is using
uint64_t magic; uint64_t magic;
}; };
@ -52,7 +52,7 @@ void *kalloc_new(size_t size) {
} }
struct page_header *header = addr; struct page_header *header = addr;
header->magic = 0xBEEFCAFE; header->magic = 0xBEEFCAFE;
header->used = size; header->used = size;
header->free = free; header->free = free;
header->prev = end_header; header->prev = end_header;

View file

@ -113,7 +113,7 @@ void virtaddr_init(void) {
} }
static void merge_back(struct addr_node *node) { static void merge_back(struct addr_node *node) {
while(node->prev) { while (node->prev) {
if (node->is_alloc != node->prev->is_alloc) if (node->is_alloc != node->prev->is_alloc)
break; break;
struct addr_node *temp = node->prev; struct addr_node *temp = node->prev;
@ -129,7 +129,7 @@ static void merge_back(struct addr_node *node) {
} }
static void merge_forward(struct addr_node *node) { static void merge_forward(struct addr_node *node) {
while(node->next) { while (node->next) {
if (node->is_alloc != node->next->is_alloc) if (node->is_alloc != node->next->is_alloc)
break; break;
struct addr_node *temp = node->next; struct addr_node *temp = node->next;

View file

@ -4,7 +4,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#define SCREEN_WIDTH 1024 #define SCREEN_WIDTH 1024
#define SCREEN_HEIGHT 768 #define SCREEN_HEIGHT 768
#define SCREEN_BIT_DEPTH 32 #define SCREEN_BIT_DEPTH 32