diff --git a/.gitignore b/.gitignore index 5227fea..39b76ba 100644 --- a/.gitignore +++ b/.gitignore @@ -21,5 +21,6 @@ purgatory.h serial.log test_fat32 test_fat32_disk +test_io_buf test_loader uki_disk diff --git a/Makefile b/Makefile index 83b973d..0f89f74 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,12 @@ MAKEFLAGS += --no-builtin-rules .SILENT: -UNIT_TESTS := loader fat32 +UNIT_TESTS := loader fat32 io_buf .PHONY: all clean distclean test unit_tests qemu_test uki_test kexec_test emu_test $(UNIT_TESTS:%=run_test_%) CC := gcc CC_X86 := x86_64-linux-gnu-gcc -CFLAGS := -std=c23 -Os -g -Wall -Wextra -Wdeclaration-after-statement -Werror -fpack-struct -fno-builtin +CFLAGS := -std=c23 -Os -g -Wall -Wextra -Wdeclaration-after-statement -Werror -Wno-address-of-packed-member -fpack-struct -fno-builtin CFLAGS_USER := $(CFLAGS) -DNO_STATIC_INTERNALS CFLAGS_M16 := $(CFLAGS) -m16 -march=i386 -nostdinc -ffreestanding -fno-pic -fno-stack-protector -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-exceptions -ffunction-sections -fdata-sections @@ -90,6 +90,8 @@ test_loader: lib.emu.o gpt.emu.o fat32.emu.o io_buf.emu.o loader.emu.o test_fat32: lib.emu.o gpt.emu.o fat32.emu.o io_buf.emu.o +test_io_buf: io_buf.emu.o + test_fat32_inputs := test_fat32_disk test_fat32_disk: make_test_fat32_disk.sh diff --git a/bios_services.h b/bios_services.h index cd21c7f..a82e46c 100644 --- a/bios_services.h +++ b/bios_services.h @@ -2,10 +2,10 @@ #include "prefix.h" -void PREFIX(halt)(); -void PREFIX(reset)(); +void PREFIX(halt)(void); +void PREFIX(reset)(void); void PREFIX(print_char)(char c); int16 PREFIX(disk_read)(uint8 *buffer, uint16 sectors, uint32 lba); int16 PREFIX(disk_write)(const uint8 *buffer, uint16 sectors, uint32 lba); int16 PREFIX(mem_move)(uint8 *dst, const uint8 *src, uint32 len); -void PREFIX(exec_kernel)(); +void PREFIX(exec_kernel)(void); diff --git a/fat32.c b/fat32.c index e91a00c..d47d47d 100644 --- a/fat32.c +++ b/fat32.c @@ -87,14 +87,17 @@ static struct { int32 entry_index; } file; -static uint32 load_dir(struct fat32_dir_entry *entries, uint32 capacity); -static int16 store_dir(const struct fat32_dir_entry *entries, uint32 entries_len); -static int16 for_each_dir_entry_loaded(struct fat32_dir_entry *entries, uint32 entries_len, void (*callback)(const char *entry_name, uint32 entry_cluster, uint32 entry_size)); -static int16 open_loaded(struct fat32_dir_entry *entries, uint32 entries_len, const char *name); -static int16 unlink_loaded(struct fat32_dir_entry *entries); -static int16 link_loaded(struct fat32_dir_entry *entries, uint32 entries_len, const char *name); -static int16 rename_loaded(struct fat32_dir_entry *entries, uint32 entries_len, const char *name); -static int16 chdir_loaded(struct fat32_dir_entry *entries, uint32 entries_len, const char *dir); +static struct { + uint32 current_dir; + uint16 is_valid; + struct fat32_dir_entry *buf; + uint32 num_entries; +} dir_cache; + +static int16 load_dir(void); +static int16 write_dir(void); +static int16 unlink_loaded(void); +static int16 link_loaded(const char *name); static int16 check_bpb(struct fat32_bpb *bpb) { @@ -131,11 +134,18 @@ static int16 check_bpb(struct fat32_bpb *bpb) return 0; } -int16 load_fat32() +int16 load_fat32(void) { int16 error; + auto_release uint8 *io_buf = (void *) 0; struct fat32_bpb *bpb; + io_buf = acquire_io_buf_hard(); + if (!io_buf) { + print_str("Failed to acquire io_buf\r\n"); + return -1; + } + error = esp_read(io_buf, 0x0001, 0x0000); if (error != 0) return error; @@ -201,29 +211,55 @@ static char * decode_name(struct fat32_dir_entry *entry) return buf; } -static uint32 load_dir(struct fat32_dir_entry *entries, uint32 capacity) +static int16 load_dir(void) { - uint32 read_sectors; + uint8 *io_buf; + uint8 file_save[sizeof(file)]; + + if (dir_cache.is_valid && dir_cache.current_dir == fs.current_dir) return 0; + + io_buf = acquire_io_buf_soft(&dir_cache.is_valid); + if (!io_buf) { + print_str("Failed to acquire io_buf\r\n"); + return -1; + } + + dir_cache.buf = (struct fat32_dir_entry *) io_buf; + dir_cache.current_dir = fs.current_dir; + dir_cache.num_entries = io_buf_len / sizeof(struct fat32_dir_entry); + + memcpy(file_save, &file, sizeof(file)); file.size = 0x00000000; file.start_cluster = fs.current_dir; reset_seek(); - read_sectors = read((uint8 *) entries, capacity / 0x0010); - return read_sectors * 0x0010; + if (read((uint8 *) dir_cache.buf, io_buf_len / 0x0200) == 0) { + dir_cache.is_valid = 0; + memcpy(&file, file_save, sizeof(file)); + return -1; + } + + memcpy(&file, file_save, sizeof(file)); + return 0; } -static int16 store_dir(const struct fat32_dir_entry *entries, uint32 entries_len) +static int16 write_dir(void) { - uint32 sectors; + uint8 file_save[sizeof(file)]; + uint32 written; + + memcpy(file_save, &file, sizeof(file)); file.size = 0x00000000; file.start_cluster = fs.current_dir; reset_seek(); - sectors = (entries_len + 0x000f) / 0x0010; - if (write((const uint8 *) entries, sectors) != sectors) return -1; + written = write((const uint8 *) dir_cache.buf, io_buf_len / 0x0200); + + memcpy(&file, file_save, sizeof(file)); + if (written == 0) return -1; return 0; } @@ -277,20 +313,19 @@ static struct fat32_dir_entry * next_entry(struct fat32_dir_entry **entries, uin int16 for_each_dir_entry(void (*callback)(const char *entry_name, uint32 entry_cluster, uint32 entry_size)) { + int16 error; + struct fat32_dir_entry *entries; uint32 entries_len; - - entries_len = load_dir((struct fat32_dir_entry *) io_buf, 0x00000800); - if (entries_len == 0) return -1; - - return for_each_dir_entry_loaded((struct fat32_dir_entry *) io_buf, entries_len, callback); -} - -static int16 for_each_dir_entry_loaded(struct fat32_dir_entry *entries, uint32 entries_len, void (*callback)(const char *entry_name, uint32 entry_cluster, uint32 entry_size)) -{ struct fat32_dir_entry *entry; char *entry_name; uint32 entry_cluster; + error = load_dir(); + if (error != 0) return error; + + entries = dir_cache.buf; + entries_len = dir_cache.num_entries; + while ((entry = next_entry(&entries, &entries_len, &entry_name)) != (void *) 0) { entry_cluster = (((uint32) entry->cluster_high) << 0x10) + entry->cluster_low; callback(entry_name, entry_cluster, entry->size); @@ -309,26 +344,24 @@ void open_cluster(uint32 cluster, uint32 size) int16 open(const char *name) { - uint32 entries_len; - - entries_len = load_dir((struct fat32_dir_entry *) io_buf, 0x00000800); - if (entries_len == 0) return -1; - - return open_loaded((struct fat32_dir_entry *) io_buf, entries_len, name); -} - -static int16 open_loaded(struct fat32_dir_entry *entries_start, uint32 entries_len, const char *name) -{ + int16 error; + struct fat32_dir_entry *entries_start; struct fat32_dir_entry *entries; + uint32 entries_len; struct fat32_dir_entry *entry; char *entry_name; + error = load_dir(); + if (error != 0) return error; + file.size = 0x00000000; file.start_cluster = fs.current_dir; file.entry_index = -1; reset_seek(); - entries = entries_start; + entries_start = dir_cache.buf; + entries = entries_start; + entries_len = dir_cache.num_entries; while ((entry = next_entry(&entries, &entries_len, &entry_name)) != (void *) 0) { if (streq(entry_name, name)) { @@ -341,25 +374,32 @@ static int16 open_loaded(struct fat32_dir_entry *entries_start, uint32 entries_l return -1; } -int16 unlink() +int16 unlink(void) { int16 error; - uint32 entries_len; - entries_len = load_dir((struct fat32_dir_entry *) io_buf, 0x00000800); - if (entries_len == 0) return -1; + error = load_dir(); + if (error != 0) return error; - error = unlink_loaded((struct fat32_dir_entry *) io_buf); + error = unlink_loaded(); if (error != 0) return error; - return store_dir((struct fat32_dir_entry *) io_buf, entries_len); + return write_dir(); } -static int16 unlink_loaded(struct fat32_dir_entry *entries) +static int16 unlink_loaded(void) { + struct fat32_dir_entry *entries; int32 lfn_start; int32 i; + if (!dir_cache.is_valid || dir_cache.current_dir != fs.current_dir) { + print_str("Directory cache not loaded\r\n"); + return -1; + } + + entries = dir_cache.buf; + if (file.entry_index < 0) { print_str("No file opened\r\n"); return -1; @@ -521,27 +561,19 @@ static void write_short_entry(struct fat32_dir_entry *entry, const char *short_n int16 link(const char *name) { int16 error; - uint32 entries_len; - uint32 cluster; - uint32 size; - cluster = file.start_cluster; - size = file.size; - - entries_len = load_dir((struct fat32_dir_entry *) io_buf, 0x00000800); - if (entries_len == 0) return -1; - - file.start_cluster = cluster; - file.size = size; + error = load_dir(); + if (error != 0) return error; - error = link_loaded((struct fat32_dir_entry *) io_buf, entries_len, name); + error = link_loaded(name); if (error != 0) return error; - return store_dir((struct fat32_dir_entry *) io_buf, entries_len); + return write_dir(); } -static int16 link_loaded(struct fat32_dir_entry *entries, uint32 entries_len, const char *name) +static int16 link_loaded(const char *name) { + struct fat32_dir_entry *entries; uint16 lfn_count; uint32 needed; int32 slot; @@ -553,6 +585,13 @@ static int16 link_loaded(struct fat32_dir_entry *entries, uint32 entries_len, co uint32 cluster; uint32 size; + if (!dir_cache.is_valid || dir_cache.current_dir != fs.current_dir) { + print_str("Directory cache not loaded\r\n"); + return -1; + } + + entries = dir_cache.buf; + cluster = file.start_cluster; size = file.size; @@ -563,12 +602,12 @@ static int16 link_loaded(struct fat32_dir_entry *entries, uint32 entries_len, co if (file.entry_index >= 0) { int32 candidate; candidate = file.entry_index - (int32) lfn_count; - if (candidate >= 0 && check_slot(entries, entries_len, (uint32) candidate, needed)) { + if (candidate >= 0 && check_slot(entries, dir_cache.num_entries, (uint32) candidate, needed)) { slot = candidate; } } if (slot < 0) { - slot = find_free_slot(entries, entries_len, needed); + slot = find_free_slot(entries, dir_cache.num_entries, needed); } if (slot < 0) { print_str("No free directory entries\r\n"); @@ -601,33 +640,17 @@ static int16 link_loaded(struct fat32_dir_entry *entries, uint32 entries_len, co int16 rename(const char *name) { int16 error; - uint32 entries_len; - uint32 cluster; - uint32 size; - cluster = file.start_cluster; - size = file.size; - - entries_len = load_dir((struct fat32_dir_entry *) io_buf, 0x00000800); - if (entries_len == 0) return -1; - - file.start_cluster = cluster; - file.size = size; - - error = rename_loaded((struct fat32_dir_entry *) io_buf, entries_len, name); + error = load_dir(); if (error != 0) return error; - return store_dir((struct fat32_dir_entry *) io_buf, entries_len); -} - -static int16 rename_loaded(struct fat32_dir_entry *entries, uint32 entries_len, const char *name) -{ - int16 error; + error = unlink_loaded(); + if (error != 0) return error; - error = unlink_loaded(entries); + error = link_loaded(name); if (error != 0) return error; - return link_loaded(entries, entries_len, name); + return write_dir(); } int16 open_path(const char *path) @@ -657,24 +680,12 @@ int16 open_path(const char *path) } int16 chdir(const char *dir) -{ - uint32 entries_len; - - if (dir == (void *) 0) return chdir_loaded((void *) 0, 0, (void *) 0); - - entries_len = load_dir((struct fat32_dir_entry *) io_buf, 0x00000800); - if (entries_len == 0) return -1; - - return chdir_loaded((struct fat32_dir_entry *) io_buf, entries_len, dir); -} - -static int16 chdir_loaded(struct fat32_dir_entry *entries, uint32 entries_len, const char *dir) { int16 error; if (dir) { - error = open_loaded(entries, entries_len, dir); - if (error != 0x0000) return error; + error = open(dir); + if (error != 0) return error; fs.current_dir = file.start_cluster; } else { @@ -719,7 +730,7 @@ static uint32 read_fat_entry(uint32 cluster) return buf[offset]; } -void reset_seek() +void reset_seek(void) { file.current_cluster = file.start_cluster; file.offset = 0x00000000; @@ -827,7 +838,7 @@ uint32 write(const uint8 *buf, uint32 sectors) return sectors_written; } -uint32 get_size() +uint32 get_size(void) { if (file.start_cluster == 0x00000000) { print_str("No file opened\r\n"); @@ -838,7 +849,7 @@ uint32 get_size() } #ifdef NO_STATIC_INTERNALS -int32 get_entry_index() +int32 get_entry_index(void) { return file.entry_index; } diff --git a/fat32.h b/fat32.h index bfeae09..f3e0e68 100644 --- a/fat32.h +++ b/fat32.h @@ -2,17 +2,17 @@ #include "prefix.h" -int16 PREFIX(load_fat32)(); +int16 PREFIX(load_fat32)(void); int16 PREFIX(open)(const char *file); void PREFIX(open_cluster)(uint32 cluster, uint32 size); int16 PREFIX(open_path)(const char *path); int16 PREFIX(chdir)(const char *dir); -int16 PREFIX(unlink)(); +int16 PREFIX(unlink)(void); int16 PREFIX(link)(const char *name); int16 PREFIX(rename)(const char *name); int16 PREFIX(for_each_dir_entry)(void (*callback)(const char *entry_name, uint32 entry_cluster, uint32 entry_size)); -void PREFIX(reset_seek)(); +void PREFIX(reset_seek)(void); int16 PREFIX(seek)(uint32 sectors); uint32 PREFIX(read)(uint8 *buf, uint32 sectors); uint32 PREFIX(write)(const uint8 *buf, uint32 sectors); -uint32 PREFIX(get_size)(); +uint32 PREFIX(get_size)(void); diff --git a/fat32_internal.h b/fat32_internal.h index 1a1e82d..bc308e8 100644 --- a/fat32_internal.h +++ b/fat32_internal.h @@ -3,5 +3,5 @@ #include "prefix.h" #ifdef NO_STATIC_INTERNALS -int32 PREFIX(get_entry_index)(); +int32 PREFIX(get_entry_index)(void); #endif diff --git a/gpt.c b/gpt.c index 1e40101..3c73037 100644 --- a/gpt.c +++ b/gpt.c @@ -81,12 +81,19 @@ static const uint8 esp_type[0x0010] = { 0x28, 0x73, 0x2a, 0xc1, 0x1f, 0xf8, 0xd2 static uint32 esp_start = 0; static uint32 esp_end; -int16 find_esp() +int16 find_esp(void) { int16 error; + auto_release uint8 *io_buf = (void *) 0; struct gpt_header *header; struct gpt_entry *entries; + io_buf = acquire_io_buf_hard(); + if (!io_buf) { + print_str("Failed to acquire io_buf\r\n"); + return -1; + } + error = disk_read(io_buf, 0x0020, 0x0001); if (error != 0) return error; diff --git a/gpt.h b/gpt.h index d47a688..9c00394 100644 --- a/gpt.h +++ b/gpt.h @@ -2,6 +2,6 @@ #include "prefix.h" -int16 PREFIX(find_esp)(); +int16 PREFIX(find_esp)(void); int16 PREFIX(esp_read)(uint8 *buffer, uint16 sectors, uint32 sector); int16 PREFIX(esp_write)(const uint8 *buffer, uint16 sectors, uint32 sector); diff --git a/io_buf.c b/io_buf.c index 20b7c8d..f3e2989 100644 --- a/io_buf.c +++ b/io_buf.c @@ -1,4 +1,43 @@ #include "types.h" +#include "io_buf.h" -uint8 heap[0x00010000]; -uint8 *io_buf = heap; +enum io_buf_state { + IO_BUF_FREE, + IO_BUF_HARD, + IO_BUF_SOFT, +}; + +static uint8 heap[0x00010000]; +static enum io_buf_state state = IO_BUF_FREE; +static uint16 *soft_notify = (void *) 0; + +const uint32 io_buf_len = sizeof(heap); + +uint8 * acquire_io_buf_hard(void) +{ + if (state == IO_BUF_HARD) return (void *) 0; + + if (state == IO_BUF_SOFT && soft_notify) *soft_notify = 0; + + state = IO_BUF_HARD; + soft_notify = (void *) 0; + return heap; +} + +uint8 * acquire_io_buf_soft(uint16 *notify) +{ + if (state == IO_BUF_HARD) return (void *) 0; + + if (state == IO_BUF_SOFT && soft_notify) *soft_notify = 0; + + state = IO_BUF_SOFT; + soft_notify = notify; + if (notify) *notify = 1; + return heap; +} + +void release_io_buf(void) +{ + state = IO_BUF_FREE; + soft_notify = (void *) 0; +} diff --git a/io_buf.h b/io_buf.h index 5c3b748..fdcada3 100644 --- a/io_buf.h +++ b/io_buf.h @@ -1,5 +1,17 @@ #pragma once +#include "types.h" #include "prefix.h" -extern uint8 *PREFIX(io_buf); +extern const uint32 PREFIX(io_buf_len); + +uint8 * PREFIX(acquire_io_buf_hard)(void); +uint8 * PREFIX(acquire_io_buf_soft)(uint16 *notify); +void PREFIX(release_io_buf)(void); + +static inline void PREFIX(release_io_buf_cleanup)(uint8 **ptr) +{ + if (*ptr) PREFIX(release_io_buf)(); +} + +#define auto_release __attribute__((cleanup(PREFIX(release_io_buf_cleanup)))) diff --git a/lib.h b/lib.h index ea3be6d..d40a019 100644 --- a/lib.h +++ b/lib.h @@ -2,7 +2,7 @@ #include "prefix.h" -void PREFIX(flush)(); +void PREFIX(flush)(void); void PREFIX(print_str)(const char *str); uint8 PREFIX(memeq)(const void *a, const void *b, uint16 len); diff --git a/linux.c b/linux.c index c205d9a..1ec3b9d 100644 --- a/linux.c +++ b/linux.c @@ -14,9 +14,10 @@ struct setup_header *setup_header = (void *) (real_mode_kernel_code + 0x01f1); uint8 *prot_mode_kernel = (void *) 0x00100000; uint8 *initrd = (void *) 0x04000000; -int16 load_kernel() +int16 load_kernel(void) { int16 error; + auto_release uint8 *io_buf = (void *) 0; uint8 real_mode_sectors; uint32 prot_mode_size; uint32 prot_mode_sectors; @@ -50,6 +51,12 @@ int16 load_kernel() prot_mode_sectors = (prot_mode_size + 0x1ff) / 0x200; ptr = prot_mode_kernel; + io_buf = acquire_io_buf_hard(); + if (!io_buf) { + print_str("Failed to acquire io_buf\r\n"); + return -1; + } + while (prot_mode_sectors) { sectors_to_read = prot_mode_sectors > 0x80 ? 0x80 : prot_mode_sectors; @@ -63,6 +70,9 @@ int16 load_kernel() ptr += sectors_to_read * 0x0200; } + release_io_buf(); + io_buf = (void *) 0; + if (*get_initrd_path() != 0x00) { error = open_path(get_initrd_path()); if (error != 0) return error; @@ -72,6 +82,12 @@ int16 load_kernel() initrd_sectors = (initrd_size + 0x01ff) / 0x0200; ptr = initrd; + io_buf = acquire_io_buf_hard(); + if (!io_buf) { + print_str("Failed to acquire io_buf\r\n"); + return -1; + } + while (initrd_sectors) { sectors_to_read = initrd_sectors > 0x80 ? 0x80 : initrd_sectors; @@ -84,6 +100,9 @@ int16 load_kernel() initrd_sectors -= sectors_to_read; ptr += sectors_to_read * 0x0200; } + + release_io_buf(); + io_buf = (void *) 0; } if (*get_cmdline() != 0x00) { diff --git a/linux.h b/linux.h index dd70a19..afeed1c 100644 --- a/linux.h +++ b/linux.h @@ -2,4 +2,4 @@ #include "prefix.h" -int16 PREFIX(load_kernel)(); +int16 PREFIX(load_kernel)(void); diff --git a/loader.c b/loader.c index f2baa75..47e221d 100644 --- a/loader.c +++ b/loader.c @@ -277,11 +277,12 @@ static int16 cmp_entry(const struct entry *a, const struct entry *b) return cmp_version(a->version, b->version); } -int16 find_entry_conf() +int16 find_entry_conf(void) { static struct entry entry; int16 error; + auto_release uint8 *io_buf = (void *) 0; error = chdir((void *) 0); if (error != 0) return error; @@ -294,6 +295,12 @@ int16 find_entry_conf() error = for_each_dir_entry(dir_entry_callback); if (error != 0) return error; + io_buf = acquire_io_buf_hard(); + if (!io_buf) { + print_str("Failed to acquire io_buf\r\n"); + return -1; + } + for (uint16 i = 0; i < num_config_entries; ++i) { open_cluster(config_entries[i].cluster, config_entries[i].size); error = read(io_buf, 0x00000020); @@ -310,11 +317,12 @@ int16 find_entry_conf() return 0; } -int16 find_entry_uki() +int16 find_entry_uki(void) { static struct entry entry; int16 error; + auto_release uint8 *io_buf = (void *) 0; struct setup_header *setup_header; char *version_str; @@ -329,6 +337,12 @@ int16 find_entry_uki() error = for_each_dir_entry(dir_entry_callback_uki); if (error != 0) return error; + io_buf = acquire_io_buf_hard(); + if (!io_buf) { + print_str("Failed to acquire io_buf\r\n"); + return -1; + } + for (uint16 i = 0; i < num_config_entries; ++i) { open_cluster(config_entries[i].cluster, config_entries[i].size); error = read(io_buf, 0x00000002); @@ -355,7 +369,7 @@ int16 find_entry_uki() return 0; } -int16 find_entry() +int16 find_entry(void) { int16 error; @@ -390,27 +404,27 @@ int16 find_entry() return 0; } -char * get_kernel_path() +char * get_kernel_path(void) { return highest_entry.linux; } -char * get_initrd_path() +char * get_initrd_path(void) { return highest_entry.initrd; } -char * get_cmdline() +char * get_cmdline(void) { return highest_entry.options; } -uint32 get_uki_cluster() +uint32 get_uki_cluster(void) { return highest_entry.uki_cluster; } -uint32 get_uki_size() +uint32 get_uki_size(void) { return highest_entry.uki_size; } diff --git a/loader.h b/loader.h index 641ecc9..1fc74aa 100644 --- a/loader.h +++ b/loader.h @@ -2,9 +2,9 @@ #include "prefix.h" -int16 PREFIX(find_entry)(); -char * PREFIX(get_kernel_path)(); -char * PREFIX(get_initrd_path)(); -char * PREFIX(get_cmdline)(); -uint32 PREFIX(get_uki_cluster)(); -uint32 PREFIX(get_uki_size)(); +int16 PREFIX(find_entry)(void); +char * PREFIX(get_kernel_path)(void); +char * PREFIX(get_initrd_path)(void); +char * PREFIX(get_cmdline)(void); +uint32 PREFIX(get_uki_cluster)(void); +uint32 PREFIX(get_uki_size)(void); diff --git a/test_io_buf.c b/test_io_buf.c new file mode 100644 index 0000000..0a306ed --- /dev/null +++ b/test_io_buf.c @@ -0,0 +1,56 @@ +#include +#include + +#define PREFIX(name) bootloader_##name + +#include "types.h" +#include "io_buf.h" + +int main(void) +{ + uint8 *a; + uint8 *b; + uint16 notify1; + uint16 notify2; + + printf("Testing hard acquire blocks hard acquire...\n"); + a = bootloader_acquire_io_buf_hard(); + assert(a != (void *) 0); + b = bootloader_acquire_io_buf_hard(); + assert(b == (void *) 0); + bootloader_release_io_buf(); + + printf("Testing hard acquire blocks soft acquire...\n"); + a = bootloader_acquire_io_buf_hard(); + assert(a != (void *) 0); + notify1 = 0xffff; + b = bootloader_acquire_io_buf_soft(¬ify1); + assert(b == (void *) 0); + assert(notify1 == 0xffff); + bootloader_release_io_buf(); + + printf("Testing soft acquire lets hard acquire through, notify fires...\n"); + notify1 = 0; + a = bootloader_acquire_io_buf_soft(¬ify1); + assert(a != (void *) 0); + assert(notify1 == 1); + b = bootloader_acquire_io_buf_hard(); + assert(b != (void *) 0); + assert(notify1 == 0); + bootloader_release_io_buf(); + + printf("Testing soft acquire lets soft acquire through, prior notify fires...\n"); + notify1 = 0; + notify2 = 0; + a = bootloader_acquire_io_buf_soft(¬ify1); + assert(a != (void *) 0); + assert(notify1 == 1); + b = bootloader_acquire_io_buf_soft(¬ify2); + assert(b != (void *) 0); + assert(notify1 == 0); + assert(notify2 == 1); + bootloader_release_io_buf(); + + printf("All tests passed!\n"); + return 0; +}