summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authorBenji Dial <Benji3.141@gmail.com>2019-12-27 17:19:51 -0500
committerBenji Dial <Benji3.141@gmail.com>2019-12-27 17:19:51 -0500
commit58b5c8ba417fe99c01d9a48731b887ce434e797e (patch)
treea09f7d0a6543328d70f8c02be8a37c320be5ef71 /src/kernel
parent3f3f9a806dc63ad827fe28724dabe694f6e67f1e (diff)
downloadportland-os-58b5c8ba417fe99c01d9a48731b887ce434e797e.tar.gz
lots of new stuff. new memory manager, some stuff on file plumbing
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/diskio.c36
-rw-r--r--src/kernel/diskio.h52
-rw-r--r--src/kernel/files.c35
-rw-r--r--src/kernel/files.h24
-rw-r--r--src/kernel/gpt.c40
-rw-r--r--src/kernel/gpt.h69
-rw-r--r--src/kernel/main.c94
-rw-r--r--src/kernel/mem.c115
-rw-r--r--src/kernel/mem.h5
9 files changed, 361 insertions, 109 deletions
diff --git a/src/kernel/diskio.c b/src/kernel/diskio.c
new file mode 100644
index 0000000..bd08136
--- /dev/null
+++ b/src/kernel/diskio.c
@@ -0,0 +1,36 @@
+/*
+Copyright 2019 Benji Dial
+
+Permission to use, copy, modify, and/or distribute this
+software for any purpose with or without fee is hereby
+granted, provided that the above copyright notice and this
+permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS
+ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+OF THIS SOFTWARE.
+*/
+
+#include "diskio.h"
+
+uint32_t read_sectors(uint8_t drive, uint32_t start, uint32_t count, void *buffer) {
+ if ((drive >= 26) || !(drives[drive].flags & DISK_IN))
+ return 0;
+ return 0;//TODO
+}
+
+uint32_t write_sectors(uint8_t drive, uint32_t start, uint32_t count, void *buffer) {
+ if ((drive >= 26) || !(drives[drive].flags & DISK_IN))
+ return 0;
+ return 0;//TODO
+}
+
+void update_status(uint8_t drive) {
+ //TODO
+}
diff --git a/src/kernel/diskio.h b/src/kernel/diskio.h
new file mode 100644
index 0000000..2f83864
--- /dev/null
+++ b/src/kernel/diskio.h
@@ -0,0 +1,52 @@
+/*
+Copyright 2019 Benji Dial
+
+Permission to use, copy, modify, and/or distribute this
+software for any purpose with or without fee is hereby
+granted, provided that the above copyright notice and this
+permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS
+ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+OF THIS SOFTWARE.
+*/
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifndef DISKIO_H
+#define DISKIO_H
+
+enum interface {
+ FLOPPY,
+ IDE,
+ ATA
+};
+
+enum drive_flags {
+ SPUN = 0x01,
+ DISK_IN = 0x02,
+ PRESENT = 0x04
+};
+
+struct drive_info {
+ uint8_t interface;
+ uint8_t number;
+ uint8_t flags;
+ uint8_t ssize;//log_2 of B
+ uint32_t length;//in kiB/2
+};
+
+struct drive_info drives[26];
+
+uint32_t read_sectors(uint8_t drive, uint32_t start, uint32_t count, void *buffer);
+uint32_t write_sectors(uint8_t drive, uint32_t start, uint32_t count, void *buffer);
+void update_status(uint8_t drive);
+
+#endif \ No newline at end of file
diff --git a/src/kernel/files.c b/src/kernel/files.c
index 78fe664..b8a9061 100644
--- a/src/kernel/files.c
+++ b/src/kernel/files.c
@@ -18,6 +18,23 @@ OF THIS SOFTWARE.
*/
#include "files.h"
+#include "diskio.h"
+#include "gpt.h"
+
+uint8_t working_drive;
+uint8_t working_part;
+uint8_t buffer[1024];
+
+void set_working_drive(uint8_t name, uint8_t part) {
+ if ((name >= (uint8_t)'a') && (name <= (uint8_t)'z') &&
+ (drives[name - (uint8_t)'a'].flags & PRESENT))
+ working_drive = name - (uint8_t)'a';
+ if (part_info[working_drive].format & ~DIRECT)
+ working_part =
+ (part >= (uint8_t)'0') && (name <= (uint8_t)'9') &&
+ (part_info[working_drive].n_partitions > part) ?
+ (part & 0x0f) : 0;
+}
uint16_t open_file(uint8_t *name) {
return 0;//TODO
@@ -52,4 +69,22 @@ uint32_t read_line_file(uint16_t handle, uint32_t max, void *buffer) {
}
++i;
}
+}
+
+void detect_disk_parts(uint8_t drive) {
+ if ((drive >= (uint8_t)'a') && (drive <= (uint8_t)'z')) {
+ uint8_t dn = (drive & 0x1f) - 1;
+ update_status(dn);
+ if (drives[dn].flags & (PRESENT | DISK_IN)) {
+ read_sectors(dn, 0, 2, buffer);
+ if ((*(uint32_t *)&buffer[0x200] == 0x20494645) &&//EFI
+ (*(uint32_t *)&buffer[0x204] == 0x54524150)) //PART
+ part_info[dn].format = gpt_parse_pt(dn, buffer) ? GPT : UNKNOWN;
+ ;
+ }
+ else {
+ part_info[dn].format = NOT_PRESENT;
+ part_info[dn].n_partitions = 0;
+ }
+ }
} \ No newline at end of file
diff --git a/src/kernel/files.h b/src/kernel/files.h
index d9102ab..f199306 100644
--- a/src/kernel/files.h
+++ b/src/kernel/files.h
@@ -29,7 +29,30 @@ struct file_info {
uint32_t position;
};
+enum fs_format {
+ ISO9660
+};
+
+enum pt_format {
+ NOT_PRESENT = 0,
+ UNKNOWN = 1,
+ DIRECT = 2,
+ MBR = 3,
+ GPT = 4
+};
+
+struct drive_parts {
+ uint8_t format;
+ uint8_t n_partitions;
+ uint8_t partition_types[10];
+ uint32_t partition_offsets[10];
+ uint32_t partition_sizes[10];
+ void *partition_cache[10];
+};
+
+struct drive_parts part_info[26];
struct file_info file_table[65536];
+void set_working_drive(uint8_t drive, uint8_t part);
uint16_t open_file(uint8_t *name);
void close_file(uint16_t handle);
uint32_t read_file(uint16_t handle, uint32_t length, void *buffer);
@@ -37,5 +60,6 @@ void write_file(uint16_t handle, uint32_t length, void *buffer);
void seek_file(uint16_t handle, int32_t by);
uint32_t get_size(uint16_t handle);
uint32_t read_line_file(uint16_t handle, uint32_t max, void *buffer);
+void detect_disk_parts(uint8_t drive);
#endif \ No newline at end of file
diff --git a/src/kernel/gpt.c b/src/kernel/gpt.c
new file mode 100644
index 0000000..32185eb
--- /dev/null
+++ b/src/kernel/gpt.c
@@ -0,0 +1,40 @@
+/*
+Copyright 2019 Benji Dial
+
+Permission to use, copy, modify, and/or distribute this
+software for any purpose with or without fee is hereby
+granted, provided that the above copyright notice and this
+permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS
+ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+OF THIS SOFTWARE.
+*/
+
+#include "gpt.h"
+#include "files.h"
+#include "diskio.h"
+
+bool gpt_parse_pt(uint8_t dn, uint8_t *buffer) {
+ struct gpt_header *head = (struct gpt_header *)&buffer[0x200];
+ struct drive_parts *pi = part_info + dn;
+ pi->format = GPT;
+ pi->n_partitions = (head->n_parts & 0xffffff00 ? 0x000000ff : head->n_parts);
+ uint32_t part_entry_size = head->part_size;
+ struct gpt_entry *as_entries = (struct gpt_entry *)buffer;
+ for (uint8_t i = 0; i < pi->n_partitions; ++i) {
+ if (!(i % 8))
+ read_sectors(dn, 2 + i / 4, 2, buffer);
+ pi->partition_sizes[i] = ((as_entries[i % 8].last_sector + 1) >> 1) - (pi->partition_offsets[i] = ((as_entries[i % 8].sector) >> 1));
+ switch (as_entries[i % 8].id.le) {
+ //TODO
+ }
+ }
+ return true;
+} \ No newline at end of file
diff --git a/src/kernel/gpt.h b/src/kernel/gpt.h
new file mode 100644
index 0000000..fb872df
--- /dev/null
+++ b/src/kernel/gpt.h
@@ -0,0 +1,69 @@
+/*
+Copyright 2019 Benji Dial
+
+Permission to use, copy, modify, and/or distribute this
+software for any purpose with or without fee is hereby
+granted, provided that the above copyright notice and this
+permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS
+ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+OF THIS SOFTWARE.
+*/
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifndef GPT_H
+#define GPT_H
+
+struct uuid {
+ uint64_t le;
+ uint64_t be;
+} __attribute__ ((__packed__));
+
+struct gpt_header {
+ uint8_t signature[8];
+ uint32_t version;
+ uint32_t header_length;
+ uint32_t check;//crc
+ uint32_t spacing;
+ uint64_t head_sector;
+ uint64_t head_backup_sector;
+ uint64_t data_start;
+ uint64_t data_last;
+ struct uuid id;
+ uint64_t pt_sector;
+ uint32_t n_parts;
+ uint32_t part_size;
+ uint32_t pt_check;
+} __attribute__ ((__packed__));
+
+struct gpt_entry {
+ struct uuid type;
+ struct uuid id;
+ uint64_t sector;
+ uint64_t last_sector;
+ uint64_t flags;
+ uint8_t name[72];
+} __attribute__ ((__packed__));
+
+enum type_le {
+ GPT_ESP_LE = 0xc12a7328f81f11d2,
+ GPT_BOOT_LE = 0x2168614864496e6f
+};
+
+enum type_be {
+ GPT_ESP_BE = 0x3bc93ec9a0004bba,
+ GPT_BOOT_BE = 0x4946456465654e74
+};
+
+bool gpt_parse_pt(uint8_t dn, uint8_t *buffer);
+
+#endif \ No newline at end of file
diff --git a/src/kernel/main.c b/src/kernel/main.c
index 36257e9..f49d9e6 100644
--- a/src/kernel/main.c
+++ b/src/kernel/main.c
@@ -155,7 +155,8 @@ enum error_codes {
INSUFF_MEMORY = 0x00000002,
MMAP_TOO_SMALL = 0x00000003,
MISSING_RC = 0x00000004,
- BAD_RC_LINE = 0x00000005
+ BAD_RC_LINE = 0x00000005,
+ BAD_MMAP = 0x00000006
};
struct tag_start *tag_pointer;
@@ -172,7 +173,7 @@ uint32_t main(void) {
case BOOT_COMMAND:
put_sz(": boot arguments\n ");
put_sz(*(uint8_t *)(tag_pointer + 1) ?
- (uint8_t *)(tag_pointer + 1) : "No arguments");
+ (uint8_t *)(tag_pointer + 1) : (uint8_t *)"No arguments");
break;
case LOADER_NAME:
@@ -219,20 +220,22 @@ uint32_t main(void) {
break;
case MEMORY_MAP: {
+ mmap_start = (struct mmap_entry *)0;
uint32_t size = *(uint32_t *)(tag_pointer + 1);
struct mmap_tag_entry *tag = (struct mmap_tag_entry *)(tag_pointer + 2);
struct mmap_tag_entry *end = (struct mmap_tag_entry *)((uint32_t)tag_pointer + tag_pointer->size);
struct mmap_entry *entry = mmap_bss;
uint32_t bitmask = 0x00000001;
uint32_t byte = 0;
- struct mmap_entry **last_next = &mmap_start;
uint32_t usable = 0;
put_sz(": memory map\n Regions:\n");
while (tag != end) {
- if (!(tag->base & 0xffffffff00000000)) {
+ if (!(tag->base & 0xffffffff00000000) && tag->length) {
entry->base = (uint32_t)tag->base;
entry->length = (tag->base + tag->length - 1) & 0xffffffff00000000 ?
1 + ~(uint32_t)tag->base : (uint32_t)tag->length;
+ if (!entry->base)
+ mmap_start = entry;
put_sz(" 0x");
put_32_hex(entry->base);
put_sz(" - 0x");
@@ -263,8 +266,6 @@ uint32_t main(void) {
entry->whose = HARDWARE;
break;
}
- *last_next = entry;
- last_next = &entry->next;
mmap_bitmap[byte] |= bitmask;
++entry;
if (!(bitmask <<= 1)) {
@@ -279,28 +280,24 @@ uint32_t main(void) {
put_sz(" Total usable memory: 0x");
put_32_hex(usable);
- bool dirty;
- do {
- dirty = false;
- for (struct mmap_entry *current = mmap_start; current; current = current->next)
- for (struct mmap_entry *against = mmap_start; against; against = against->next)
- if ((current->base + current->length == against->base) &&
- (current->whose == against->whose)) {
- current->length += against->length;
- unmark_entry(against);
- if (against == mmap_start)
- mmap_start = against->next;
- else {
- for (current = mmap_start; current->next != against; current = current->next)
- ;
- current->next = against->next;
- }
- dirty = true;
- }
- } while (dirty);
-
- have_mmap = true;
- break;
+ for (struct mmap_entry *b = mmap_bss; b < entry; ++b)
+ for (struct mmap_entry *a = mmap_bss; a < entry; ++a)
+ if (b->base + b->length == a->base)
+ (b->after = a)->before = b;
+
+ for (struct mmap_entry *p = mmap_start; p->after; p = p->after)
+ while (p->whose == p->after->whose) {
+ p->length += p->after->whose;
+ unmark_entry(p->after);
+ if (p->after = p->after->after)
+ p->after->before = p;
+ }
+
+ if (mmap_start) {
+ have_mmap = true;
+ break;
+ }
+ return BAD_MMAP;
}
case VBE_INFO: {
@@ -408,26 +405,33 @@ uint32_t main(void) {
if (!have_mmap)
return NO_MMAP;
- put_sz("\n\nImportant locations:");
+ put_sz("\n\nInfo:");
if (have_text_base) {
- put_sz("\n Text section: 0x");
+ put_sz("\n Text section: 0x");
put_32_hex(text_base);
}
- put_sz("\n Memory map: 0x");
- put_32_hex((uint32_t)mmap_bss);
- put_sz(" - 0x");
- put_32_hex((uint32_t)mmap_bss - 1 +
- sizeof(struct mmap_entry) * MMAP_SIZE);
- put_sz("\n Process table: 0x");
- put_32_hex((uint32_t)proc_table);
- put_sz(" - 0x");
- put_32_hex((uint32_t)proc_table - 1 +
- sizeof(struct proc_info) * 65536);
- put_sz("\n File table: 0x");
- put_32_hex((uint32_t)file_table);
- put_sz(" - 0x");
- put_32_hex((uint32_t)file_table - 1 +
- sizeof(struct file_info) * 65536);
+ put_sz("\n Memory map size: 0x");
+ put_32_hex(sizeof(struct mmap_entry) * MMAP_SIZE);
+ put_sz("\n Process table size: 0x");
+ put_32_hex(sizeof(struct proc_info) * 65536);
+ put_sz("\n File table size: 0x");
+ put_32_hex(sizeof(struct file_info) * 65536);
+ put_sz("\n\nDisks:");
+
+ for (uint8_t i = 0; i < 26; ++i) {
+ detect_disk_parts((uint8_t)'a' + i);
+ if (part_info[i].format) {
+ put_sz("\n ");
+ put_char((uint8_t)'a' + i);
+ if (part_info[i].n_partitions) {
+ put_char('0');
+ uint8_t str[] = "\n 1";
+ for (uint8_t m = part_info[i].n_partitions + (uint8_t)'0'; str[4] < m; ++(str[4]))
+ put_sz(str);
+ }
+ }
+ }
+
put_sz("\n\n");
put_sz("No file support yet. Halting.");
diff --git a/src/kernel/mem.c b/src/kernel/mem.c
index 99586d9..d9322a9 100644
--- a/src/kernel/mem.c
+++ b/src/kernel/mem.c
@@ -23,75 +23,66 @@ uint32_t last_byte = 0;
uint32_t last_mask = 0x00000001;
void *allocate_block(uint32_t size, uint16_t proc_n) {
- struct mmap_entry *i = mmap_start;
- while (i->whose || (i->length < size))
- if (i->next)
- i = i->next;
- else
- return (void *)0;
- if (i->length == size) {
- i->whose = proc_n;
- return (void *)i->base;
- }
- uint32_t remaining = i->length - size;
- i->whose = proc_n;
- i->length = size;
-
- uint32_t byte = last_byte;
- uint32_t mask = last_mask;
- do {
- if (!(mask <<= 1)) {
- mask = 0x00000001;
- if (++byte == MMAP_SIZE)
- byte = 0;
+ for (struct mmap_entry *find = mmap_start; find; find = find->after)
+ if (!find->whose) {
+ if (find->length == size) {
+ find->whose = proc_n;
+ return (void *)find->base;
+ }
+ else if (find->length > size) {
+ uint32_t byte = last_byte;
+ uint32_t mask = last_mask;
+ while (mmap_bitmap[byte] & mask) {
+ if ((byte == last_byte) && (mask == last_mask)) {
+ while (find = find->after)
+ if (find->length == size) {
+ find->whose = proc_n;
+ return (void *)find->base;
+ }
+ return (void *)0;
+ }
+ if (!(mask <<= 1)) {
+ mask = 0x00000001;
+ if (++byte == MMAP_SIZE)
+ byte = 0;
+ }
+ }
+ mmap_bitmap[last_byte = byte] |= last_mask = mask;
+ struct mmap_entry *new = mmap_bss + (byte << 5);
+ while (mask >>= 1)
+ ++new;
+ ((((new->after = find->after)->before = new)->before = find)->after = new)->base = find->base + size;
+ new->length = find->length - size;
+ find->length = size;
+ find->whose = proc_n;
+ new->whose = FREE;
+ return (void *)find->base;
+ }
}
- if ((byte == last_byte) && (mask == last_mask))
- return 0;
- } while (mmap_bitmap[byte] & mask);
- last_byte = byte;
- last_mask = mask;
- mmap_bitmap[byte] |= mask;
- uint8_t bit = 0;
- while (!(mask & 0x00000001)) {
- ++bit;
- mask >>= 1;
- }
-
- struct mmap_entry *new = mmap_bss + (byte << 5) + bit;
- new->base = i->base + size;
- new->length = remaining;
- new->whose = FREE;
- new->next = i->next;
- i->next = new;
- return (void *)i->base;
+ return (void *)0;
}
void deallocate_block(void *start) {
struct mmap_entry *find = mmap_start;
while (find->base != (uint32_t)start)
- if (find->next)
- find = find->next;
+ if (find->after)
+ find = find->after;
else
return;
find->whose = FREE;
-
- for (struct mmap_entry *find_after = mmap_start; find_after; find_after = find_after->next)
- if (find_after->base == find->base + find->length) {
- if (!find_after->whose) {
- find->length += find_after->length;
- find->next = find_after->next;
- unmark_entry(find_after);
- }
- break;
- }
-
- for (struct mmap_entry *find_before = mmap_start; find_before; find_before = find_before->next)
- if (find->base == find_before->base + find_before->length) {
- if (!find_before->whose) {
- find_before->length += find->length;
- find_before->next = find->next;
- unmark_entry(find);
- }
- break;
- }
+ while (find->before && !find->before->whose) {
+ find->before->length += find->length;
+ if (find->before->after = find->after)
+ find->after->before = find->before;
+ unmark_entry(find);
+ find = find->before;
+ }
+ if (!find->before)
+ mmap_start = find;
+ while (find->after && !find->after->whose) {
+ find->length += find->after->length;
+ unmark_entry(find->after);
+ if (find->after = find->after->after)
+ find->after->before = find;
+ }
} \ No newline at end of file
diff --git a/src/kernel/mem.h b/src/kernel/mem.h
index 5c0d387..4a35978 100644
--- a/src/kernel/mem.h
+++ b/src/kernel/mem.h
@@ -32,14 +32,15 @@ struct mmap_entry {
uint32_t base;
uint32_t length;
uint16_t whose;
- struct mmap_entry *next;
+ struct mmap_entry *after;
+ struct mmap_entry *before;
};
#define MMAP_SIZE 65536
struct mmap_entry *mmap_start;
struct mmap_entry mmap_bss[MMAP_SIZE];
uint32_t mmap_bitmap[MMAP_SIZE / 32];
-#define unmark_entry(entry) mmap_bitmap[((entry) - mmap_bss) >> 5] ^= 1 << (((entry) - mmap_bss) & 0x0000001f);
+#define unmark_entry(entry) (mmap_bitmap[((entry) - mmap_bss) >> 5] ^= 1 << (((entry) - mmap_bss) & 0x0000001f))
void *allocate_block(uint32_t size, uint16_t proc_n);
void deallocate_block(void *start);