From c542ff6845f1f15281707c2fbc340fdce29081bc Mon Sep 17 00:00:00 2001 From: mintsuki Date: Mon, 2 Nov 2020 09:20:34 +0100 Subject: [PATCH] Some general cleanup --- limine.bin | Bin 32768 -> 32768 bytes stage2/lib/blib.c | 161 +-------------------------------------- stage2/lib/blib.h | 20 +---- stage2/lib/config.c | 39 ---------- stage2/lib/config.h | 1 - stage2/lib/guid.c | 58 ++++++++++++++ stage2/lib/guid.h | 17 +++++ stage2/lib/part.c | 1 + stage2/lib/part.h | 2 +- stage2/lib/readline.c | 23 ++++++ stage2/lib/readline.h | 7 ++ stage2/lib/uri.c | 119 +++++++++++++++++++++++++++++ stage2/lib/uri.h | 10 +++ stage2/menu.c | 1 + stage2/protos/linux.c | 1 + stage2/protos/stivale.c | 1 + stage2/protos/stivale2.c | 1 + 17 files changed, 244 insertions(+), 218 deletions(-) create mode 100644 stage2/lib/guid.c create mode 100644 stage2/lib/guid.h create mode 100644 stage2/lib/uri.c create mode 100644 stage2/lib/uri.h diff --git a/limine.bin b/limine.bin index 3d3503ed87d6d08ac9618d305e65603680e6cbe0..72b6abbce1c8c097f40b668941550743b058844f 100644 GIT binary patch delta 22934 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�^X6PZF*TsKrqyuGB1IZ&3N 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 LixnwFYm znm!{rO*L=2!Dx79%B-a1naXpjVXA-fG%eL&nC&l-I%j_1d6wCrJQ|ax0pKL%E&0i$ z+1+)Y43tToHe+^=7syVUIs(%LeTO!wx>l*qQy|BS|&W zkUHBi>zQQZ)LAoT8-NHu)v13>sdMJdNuDz+@W3SmOl)3m9vB^~Ef17wj=wGuFzETV z(%mvvSOmhKpHp0rvy9{$b-N$fMBO|K7?)&|xmz?8(a}9V{*h;a4k(tRyUSxy^h6$e zWLZuLKr90D+bwSqs?kbGOLlR0CDgK@!wWz`gO)|8pm4jjZFj-pBDH_%&k5+Ti0&dO zn4ZT`4Kgo5K+?GS*9D;xES3MZT+YhHIXT%@8apy7pa$vLRt&oKKU4;+tjmEf{2s@@ z1<-g8Dg=kC+wurx>j6F$3ljtx!|Zs>p^w0$$2EXR3LYfwPD5oHj3Y z#_VaT?iOK8MWEt}Jez+71`s}a+Or3O+L{HbMbY+H1$_e2V0Y+;Qe?O|F(^A(EG|ZW zE2pS%u>~+R2lB=S9{yJ@9Q)t1;n*NP9Q$80;@JO!6UY8%Rvg=#O~&4t8UIzu|B@a5 zRrUXYA;M6Y;TJ5K zcw6d}9AFSAjOcWy8Va%zz-@iG1J5RzW+bbu%Zn!J7OceQOvM{o3??EkJIj`%OEU2} z1vdVOSTtHU3(M(dOy&Ly)lEs7G0QL&4TQfKR8#WO#Knt&Zn+}bm1m0!#U&P-F1Wyg zm1Fqmj!%bB~xLpl7OcS!{=uajtp_fjM+2h zr7G@2(DT2yemK7@&JKX%uLO>!s^~tcaHcwA-i$f3Ra1XcXQUhW=WSpE6IrDXL0R42 z3-~D1QJR+B?(pUmkOP@Cb__WdDn6D$(>N@y1JuyTwH4Zcps0zSv+>mkm@T4HlvT`K za2)o<-5w$Ji2hzo=Escjf8;}I)q4D4SRaom=!?gBe#6W8l)wK6l9L#jIHLdn00000 R00000006UnVuKx#AQ1aa`e6V7 delta 22931 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 O7C55-006UOVv`+T4fsm{ diff --git a/stage2/lib/blib.c b/stage2/lib/blib.c index dde26e21..7173da64 100644 --- a/stage2/lib/blib.c +++ b/stage2/lib/blib.c @@ -1,93 +1,11 @@ #include #include #include -#include #include -#include -#include -#include -#include -#include #include -#include -#include -#include uint8_t boot_drive; -// BIOS partitions are specified in the : form. -// The drive may be omitted, the partition cannot. -static bool parse_bios_partition(char *loc, uint8_t *drive, uint8_t *partition) { - for (size_t i = 0; ; i++) { - if (loc[i] == 0) - return false; - - if (loc[i] == ':') { - loc[i] = 0; - if (*loc == 0) { - *drive = boot_drive; - } else { - if (strtoui(loc) < 1 || strtoui(loc) > 16) { - panic("BIOS drive number outside range 1-16"); - } - *drive = (strtoui(loc) - 1) + 0x80; - } - loc += i + 1; - break; - } - } - - if (*loc == 0) - return false; - - if (strtoui(loc) < 1 || strtoui(loc) > 256) { - panic("BIOS partition number outside range 1-256"); - } - *partition = strtoui(loc) - 1; - - return true; -} - -static bool uri_bios_dispatch(struct file_handle *fd, char *loc, char *path) { - uint8_t drive, partition; - - if (!parse_bios_partition(loc, &drive, &partition)) - return false; - - if (fopen(fd, drive, partition, path)) - return false; - - return true; -} - -static bool uri_guid_dispatch(struct file_handle *fd, char *guid_str, char *path) { - struct guid guid; - if (!string_to_guid(&guid, guid_str)) - return false; - - int drive, partition; - if (!part_get_by_guid(&drive, &partition, &guid)) - return false; - - if (fopen(fd, drive, partition, path)) - return false; - - return true; -} - -bool uri_open(struct file_handle *fd, char *uri) { - char *resource, *root, *path; - config_resolve_uri(uri, &resource, &root, &path); - - if (!strcmp(resource, "bios")) { - return uri_bios_dispatch(fd, root, path); - } else if (!strcmp(resource, "guid")) { - return uri_guid_dispatch(fd, root, path); - } else { - panic("Resource `%s` not valid.", resource); - } -} - // This integer sqrt implementation has been adapted from: // https://stackoverflow.com/questions/1100090/looking-for-an-efficient-integer-square-root-algorithm-for-arm-thumb2 uint64_t sqrt(uint64_t a_nInput) { @@ -133,7 +51,7 @@ __attribute__((noreturn)) void panic(const char *fmt, ...) { } } -static int char_value(char c) { +int digit_to_int(char c) { if (c >= 'a' && c <= 'z') { return (c - 'a') + 10; } @@ -147,89 +65,16 @@ static int char_value(char c) { return -1; } -static bool is_valid_guid(const char *s) { - for (size_t i = 0; ; i++) { - switch (i) { - case 8: - case 13: - case 18: - case 23: - if (s[i] != '-') - return false; - break; - case 36: - return s[i] == 0; - default: - if (char_value(s[i]) == -1) - return false; - break; - } - } -} -/* -static void guid_convert_le_cluster(uint8_t *dest, const char *s, int len) { - size_t p = 0; - for (int i = len - 1; i >= 0; i--) { - int val = char_value(s[i]); - - i % 2 ? (dest[p] = val) : (dest[p++] |= val << 4); - } -} -*/ -static void guid_convert_be_cluster(uint8_t *dest, const char *s, int len) { - size_t p = 0; - for (int i = 0; i < len; i++) { - int val = char_value(s[i]); - - i % 2 ? (dest[p++] |= val) : (dest[p] = val << 4); - } -} - -bool string_to_guid(struct guid *guid, const char *s) { - if (!is_valid_guid(s)) - return false; - - guid_convert_be_cluster((uint8_t *)guid + 0, s + 0, 8); - guid_convert_be_cluster((uint8_t *)guid + 4, s + 9, 4); - guid_convert_be_cluster((uint8_t *)guid + 6, s + 14, 4); - guid_convert_be_cluster((uint8_t *)guid + 8, s + 19, 4); - guid_convert_be_cluster((uint8_t *)guid + 10, s + 24, 12); - - return true; -} - uint64_t strtoui(const char *s) { uint64_t n = 0; while (*s) - n = n * 10 + char_value(*(s++)); + n = n * 10 + digit_to_int(*(s++)); return n; } uint64_t strtoui16(const char *s) { uint64_t n = 0; while (*s) - n = n * 16 + char_value(*(s++)); + n = n * 16 + digit_to_int(*(s++)); return n; } - -int getchar_internal(uint32_t eax) { - switch ((eax >> 8) & 0xff) { - case 0x4b: - return GETCHAR_CURSOR_LEFT; - case 0x4d: - return GETCHAR_CURSOR_RIGHT; - case 0x48: - return GETCHAR_CURSOR_UP; - case 0x50: - return GETCHAR_CURSOR_DOWN; - case 0x53: - return GETCHAR_DELETE; - } - return (char)(eax & 0xff); -} - -int getchar(void) { - struct rm_regs r = {0}; - rm_int(0x16, &r, &r); - return getchar_internal(r.eax); -} diff --git a/stage2/lib/blib.h b/stage2/lib/blib.h index d1bccbeb..5f124128 100644 --- a/stage2/lib/blib.h +++ b/stage2/lib/blib.h @@ -4,36 +4,18 @@ #include #include #include -#include extern uint8_t boot_drive; -struct guid { - uint32_t a; - uint16_t b; - uint16_t c; - uint8_t d[8]; -} __attribute__((packed)); - -bool string_to_guid(struct guid *guid, const char *s); - -bool uri_open(struct file_handle *fd, char *uri); - uint64_t sqrt(uint64_t a_nInput); +int digit_to_int(char c); uint8_t bcd_to_int(uint8_t val); __attribute__((noreturn)) void panic(const char *fmt, ...); int pit_sleep_and_quit_on_keypress(uint32_t pit_ticks); -#define GETCHAR_CURSOR_LEFT (-10) -#define GETCHAR_CURSOR_RIGHT (-11) -#define GETCHAR_CURSOR_UP (-12) -#define GETCHAR_CURSOR_DOWN (-13) -#define GETCHAR_DELETE (-14) - -int getchar(void); uint64_t strtoui(const char *s); uint64_t strtoui16(const char *s); diff --git a/stage2/lib/config.c b/stage2/lib/config.c index d81b4633..28723455 100644 --- a/stage2/lib/config.c +++ b/stage2/lib/config.c @@ -121,42 +121,3 @@ char *config_get_value(char *buf, size_t index, size_t limit, const char *key) { return NULL; } - -// A URI takes the form of: resource://root/path -// The following function splits up a URI into its componenets -bool config_resolve_uri(char *uri, char **resource, char **root, char **path) { - *resource = *root = *path = NULL; - - // Get resource - for (size_t i = 0; ; i++) { - if (strlen(uri + i) < 3) - return false; - - if (!memcmp(uri + i, "://", 3)) { - *resource = uri; - uri[i] = 0; - uri += i + 3; - break; - } - } - - // Get root - for (size_t i = 0; ; i++) { - if (uri[i] == 0) - return false; - - if (uri[i] == '/') { - *root = uri; - uri[i] = 0; - uri += i + 1; - break; - } - } - - // Get path - if (*uri == 0) - return false; - *path = uri; - - return true; -} diff --git a/stage2/lib/config.h b/stage2/lib/config.h index b5a0108b..f5c2adc3 100644 --- a/stage2/lib/config.h +++ b/stage2/lib/config.h @@ -10,6 +10,5 @@ int init_config(int drive, int part); int config_get_entry_name(char *ret, size_t index, size_t limit); int config_set_entry(size_t index); char *config_get_value(char *buf, size_t index, size_t limit, const char *key); -bool config_resolve_uri(char *uri, char **resource, char **root, char **path); #endif diff --git a/stage2/lib/guid.c b/stage2/lib/guid.c new file mode 100644 index 00000000..0349372d --- /dev/null +++ b/stage2/lib/guid.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include + +bool is_valid_guid(const char *s) { + for (size_t i = 0; ; i++) { + switch (i) { + case 8: + case 13: + case 18: + case 23: + if (s[i] != '-') + return false; + break; + case 36: + return s[i] == 0; + default: + if (digit_to_int(s[i]) == -1) + return false; + break; + } + } +} + +/* +static void guid_convert_le_cluster(uint8_t *dest, const char *s, int len) { + size_t p = 0; + for (int i = len - 1; i >= 0; i--) { + int val = digit_to_int(s[i]); + + i % 2 ? (dest[p] = val) : (dest[p++] |= val << 4); + } +} +*/ + +static void guid_convert_be_cluster(uint8_t *dest, const char *s, int len) { + size_t p = 0; + for (int i = 0; i < len; i++) { + int val = digit_to_int(s[i]); + + i % 2 ? (dest[p++] |= val) : (dest[p] = val << 4); + } +} + +bool string_to_guid(struct guid *guid, const char *s) { + if (!is_valid_guid(s)) + return false; + + guid_convert_be_cluster((uint8_t *)guid + 0, s + 0, 8); + guid_convert_be_cluster((uint8_t *)guid + 4, s + 9, 4); + guid_convert_be_cluster((uint8_t *)guid + 6, s + 14, 4); + guid_convert_be_cluster((uint8_t *)guid + 8, s + 19, 4); + guid_convert_be_cluster((uint8_t *)guid + 10, s + 24, 12); + + return true; +} diff --git a/stage2/lib/guid.h b/stage2/lib/guid.h new file mode 100644 index 00000000..b1a787e3 --- /dev/null +++ b/stage2/lib/guid.h @@ -0,0 +1,17 @@ +#ifndef __LIB__GUID_H__ +#define __LIB__GUID_H__ + +#include +#include + +struct guid { + uint32_t a; + uint16_t b; + uint16_t c; + uint8_t d[8]; +} __attribute__((packed)); + +bool is_valid_guid(const char *s); +bool string_to_guid(struct guid *guid, const char *s); + +#endif diff --git a/stage2/lib/part.c b/stage2/lib/part.c index bb5aa82f..2e1a84db 100644 --- a/stage2/lib/part.c +++ b/stage2/lib/part.c @@ -7,6 +7,7 @@ #include #include #include +#include #define NO_PARTITION (-1) #define INVALID_TABLE (-2) diff --git a/stage2/lib/part.h b/stage2/lib/part.h index e7304b10..e718577f 100644 --- a/stage2/lib/part.h +++ b/stage2/lib/part.h @@ -3,7 +3,7 @@ #include #include -#include +#include struct part { int drive; diff --git a/stage2/lib/readline.c b/stage2/lib/readline.c index bf752321..10923ca4 100644 --- a/stage2/lib/readline.c +++ b/stage2/lib/readline.c @@ -4,6 +4,29 @@ #include #include #include +#include + +int getchar_internal(uint32_t eax) { + switch ((eax >> 8) & 0xff) { + case 0x4b: + return GETCHAR_CURSOR_LEFT; + case 0x4d: + return GETCHAR_CURSOR_RIGHT; + case 0x48: + return GETCHAR_CURSOR_UP; + case 0x50: + return GETCHAR_CURSOR_DOWN; + case 0x53: + return GETCHAR_DELETE; + } + return (char)(eax & 0xff); +} + +int getchar(void) { + struct rm_regs r = {0}; + rm_int(0x16, &r, &r); + return getchar_internal(r.eax); +} static void reprint_string(int x, int y, const char *s) { int orig_x, orig_y; diff --git a/stage2/lib/readline.h b/stage2/lib/readline.h index 44061fa3..ba09a7d1 100644 --- a/stage2/lib/readline.h +++ b/stage2/lib/readline.h @@ -3,6 +3,13 @@ #include +#define GETCHAR_CURSOR_LEFT (-10) +#define GETCHAR_CURSOR_RIGHT (-11) +#define GETCHAR_CURSOR_UP (-12) +#define GETCHAR_CURSOR_DOWN (-13) +#define GETCHAR_DELETE (-14) + +int getchar(void); void readline(const char *orig_str, char *buf, size_t limit); #endif diff --git a/stage2/lib/uri.c b/stage2/lib/uri.c new file mode 100644 index 00000000..eafe13c3 --- /dev/null +++ b/stage2/lib/uri.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include +#include + +// A URI takes the form of: resource://root/path +// The following function splits up a URI into its componenets +bool uri_resolve(char *uri, char **resource, char **root, char **path) { + *resource = *root = *path = NULL; + + // Get resource + for (size_t i = 0; ; i++) { + if (strlen(uri + i) < 3) + return false; + + if (!memcmp(uri + i, "://", 3)) { + *resource = uri; + uri[i] = 0; + uri += i + 3; + break; + } + } + + // Get root + for (size_t i = 0; ; i++) { + if (uri[i] == 0) + return false; + + if (uri[i] == '/') { + *root = uri; + uri[i] = 0; + uri += i + 1; + break; + } + } + + // Get path + if (*uri == 0) + return false; + *path = uri; + + return true; +} + +// BIOS partitions are specified in the : form. +// The drive may be omitted, the partition cannot. +static bool parse_bios_partition(char *loc, uint8_t *drive, uint8_t *partition) { + for (size_t i = 0; ; i++) { + if (loc[i] == 0) + return false; + + if (loc[i] == ':') { + loc[i] = 0; + if (*loc == 0) { + *drive = boot_drive; + } else { + if (strtoui(loc) < 1 || strtoui(loc) > 16) { + panic("BIOS drive number outside range 1-16"); + } + *drive = (strtoui(loc) - 1) + 0x80; + } + loc += i + 1; + break; + } + } + + if (*loc == 0) + return false; + + if (strtoui(loc) < 1 || strtoui(loc) > 256) { + panic("BIOS partition number outside range 1-256"); + } + *partition = strtoui(loc) - 1; + + return true; +} + +static bool uri_bios_dispatch(struct file_handle *fd, char *loc, char *path) { + uint8_t drive, partition; + + if (!parse_bios_partition(loc, &drive, &partition)) + return false; + + if (fopen(fd, drive, partition, path)) + return false; + + return true; +} + +static bool uri_guid_dispatch(struct file_handle *fd, char *guid_str, char *path) { + struct guid guid; + if (!string_to_guid(&guid, guid_str)) + return false; + + int drive, partition; + if (!part_get_by_guid(&drive, &partition, &guid)) + return false; + + if (fopen(fd, drive, partition, path)) + return false; + + return true; +} + +bool uri_open(struct file_handle *fd, char *uri) { + char *resource, *root, *path; + uri_resolve(uri, &resource, &root, &path); + + if (!strcmp(resource, "bios")) { + return uri_bios_dispatch(fd, root, path); + } else if (!strcmp(resource, "guid")) { + return uri_guid_dispatch(fd, root, path); + } else { + panic("Resource `%s` not valid.", resource); + } +} diff --git a/stage2/lib/uri.h b/stage2/lib/uri.h new file mode 100644 index 00000000..1fb65f43 --- /dev/null +++ b/stage2/lib/uri.h @@ -0,0 +1,10 @@ +#ifndef __LIB__URI_H__ +#define __LIB__URI_H__ + +#include +#include + +bool uri_resolve(char *uri, char **resource, char **root, char **path); +bool uri_open(struct file_handle *fd, char *uri); + +#endif diff --git a/stage2/menu.c b/stage2/menu.c index 76e486b8..afc11a09 100644 --- a/stage2/menu.c +++ b/stage2/menu.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include diff --git a/stage2/protos/linux.c b/stage2/protos/linux.c index 62261882..be91c436 100644 --- a/stage2/protos/linux.c +++ b/stage2/protos/linux.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff --git a/stage2/protos/stivale.c b/stage2/protos/stivale.c index cdbd144c..980a02d1 100644 --- a/stage2/protos/stivale.c +++ b/stage2/protos/stivale.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/stage2/protos/stivale2.c b/stage2/protos/stivale2.c index 59708522..61b2073c 100644 --- a/stage2/protos/stivale2.c +++ b/stage2/protos/stivale2.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include