[MBR] add pos-jump signature (for future checks)

[LIBFAT] Add file creation and writing capabilities
This commit is contained in:
John Stefanelli 2022-09-25 12:10:22 -04:00
parent 58de4d6c32
commit ad55abdeb0
Signed by: jstefanelli
GPG key ID: 60EDE2437640D2AA
4 changed files with 381 additions and 30 deletions

View file

@ -80,7 +80,7 @@ int main(int argc, char** argv) {
return 1;
}
FILE* f = fopen(argv[1], "rb");
FILE* f = fopen(argv[1], "rb+");
FileHandle h;
h.read = readRoutine;

View file

@ -89,6 +89,10 @@ OS_PACK_END;
#define FAT_ARCHIVE_BIT 32
#define FAT_LAST_CLUSTER_32 0xFFFFFFF8
#define FAT_LAST_CLUSTER_32_2 0xFFFFFFFF
#define FAT_FSINFO_SIG_0 0x41615252
#define FAT_FSINFO_SIG_1 0x61417272
OS_PACK_START
struct _FatDirectoryEntry {
@ -108,6 +112,12 @@ typedef struct _FatDirectoryEntry FatDirectoryEntry;
typedef struct _FatHeader_32 FatHeader_32;
typedef struct _LibFatDirectoryEntry {
FatDirectoryEntry entry;
os_u32 entry_cluster;
os_u32 entry_offset;
} LibFatDirectoryEntry;
typedef struct _FatControlBlock {
FileHandle handle;
FatHeader_32 header;
@ -118,11 +128,10 @@ typedef struct _FatControlBlock {
typedef struct _LibFatFile {
FatControlBlock* fat;
FatDirectoryEntry file_entry;
LibFatDirectoryEntry file_entry;
os_u32 current_cluster;
os_u32 position;
os_u32 in_cluster_position;
os_u32 fat_data_offset;
os_u32 fat_cluster_size;
} LibFatFile;
@ -137,11 +146,16 @@ typedef struct _LibFatDirectory {
extern os_bool libfat_init(FileHandle handle, void* buffer, os_u32 buffer_size, FatControlBlock* result);
extern os_bool libfat_open_read(FatControlBlock* fat, FatDirectoryEntry* entry, LibFatFile* result);
extern os_bool libfat_open(FatControlBlock* fat, LibFatDirectoryEntry* entry, LibFatFile* result);
extern os_u32 libfat_read(LibFatFile* file, void* buffer, os_u32 buffer_size);
extern os_u32 libfat_write(LibFatFile* file, void* biffer, os_u32 buffer_size);
extern os_bool libfat_seek(LibFatFile* file, os_s32 position, os_u32 direction);
extern os_u32 libfat_tell(LibFatFile* file);
extern os_bool libfat_open_directory(FatControlBlock* fat, FatDirectoryEntry* entry, LibFatDirectory* result);
extern void libfat_test(FileHandle image_file, PrintRoutine print, PrintNumber rintNumber);
extern os_bool libfat_create(FatControlBlock* fat, LibFatDirectoryEntry* parent_entry, os_s8* name, os_bool directory, LibFatDirectoryEntry* result);
extern os_bool libfat_open_directory(FatControlBlock* fat, LibFatDirectoryEntry* entry, LibFatDirectory* result);
extern os_bool libfat_read_directory(LibFatDirectory* dir, LibFatDirectoryEntry* entry);
extern void libfat_test(FileHandle handle, PrintRoutine print, PrintNumber printNumber);
#endif //!__OS3_LIBFAT_H

View file

@ -50,7 +50,7 @@ os_bool libfat_load_fat_cluster(FatControlBlock* fat, os_u32 target_cluster, os_
fat->first_loaded_cluster + fat->loaded_fat_cluster_amount <= target_cluster ||
force != OS_FALSE) {
os_u32 fat_size = fat->header.sectors_per_fat_32 * fat->header.base.bytes_per_sector;
os_u32 fat_offset = (fat->header.base.bytes_per_sector * fat->header.base.reserved_sectors) + fat_size;
os_u32 fat_offset = (fat->header.base.bytes_per_sector * fat->header.base.reserved_sectors);
fat->handle.seek(fat_offset, LIBFAT_SEEK_ORIGIN, fat->handle.user_data);
os_u32 fat_clusters = fat_size / sizeof(os_u32);
@ -77,6 +77,28 @@ os_u32 libfat_read_cluster(FatControlBlock* fat, os_u32 cluster) {
return fat->loaded_fat_segment[cluster - fat->first_loaded_cluster];
}
os_bool libfat_write_fat_cluster(FatControlBlock* fat, os_u32 cluster_id, os_u32 cluster_value) {
os_u32 fat_size = fat->header.sectors_per_fat_32 * fat->header.base.bytes_per_sector;
if (cluster_id < 2 || cluster_id >= fat_size / sizeof(os_u32)) {
return OS_FALSE;
}
os_u32 first_fat_offset = (fat->header.base.reserved_sectors * fat->header.base.bytes_per_sector);
os_u32 second_fat_offset = first_fat_offset + fat_size;
os_u32 fisrt_fat_cluster_offset = first_fat_offset + (cluster_id * sizeof(os_u32));
os_u32 second_fat_cluster_offset = second_fat_offset + (cluster_id * sizeof(os_u32));
fat->handle.seek(fisrt_fat_cluster_offset, LIBFAT_SEEK_ORIGIN, fat->handle.user_data);
fat->handle.write(sizeof(os_u32), (void*)&cluster_value, fat->handle.user_data);
fat->handle.seek(second_fat_cluster_offset, LIBFAT_SEEK_ORIGIN, fat->handle.user_data);
fat->handle.write(sizeof(os_u32), (void*)&cluster_value, fat->handle.user_data);
return OS_TRUE;
}
os_u32 libfat_load_cluster(FatControlBlock* fat, os_u32 cluster, void* buffer, os_u32 buffer_size, os_u32 offset_in_cluster) {
os_u32 cluster_size = fat->header.base.bytes_per_sector * fat->header.base.sectors_per_cluster;
os_u32 data_offset = (fat->header.base.reserved_sectors + (fat->header.sectors_per_fat_32 * fat->header.base.number_of_fats)) * fat->header.base.bytes_per_sector;
@ -98,39 +120,54 @@ os_u32 libfat_load_cluster(FatControlBlock* fat, os_u32 cluster, void* buffer, o
}
os_bool libfat_open_read(FatControlBlock* fat, FatDirectoryEntry* entry, LibFatFile* result) {
os_u32 libfat_write_cluster(FatControlBlock* fat, os_u32 cluster, void* buffer, os_u32 buffer_size, os_u32 offset_in_cluster) {
os_u32 cluster_size = fat->header.base.bytes_per_sector * fat->header.base.sectors_per_cluster;
os_u32 data_offset = (fat->header.base.reserved_sectors + (fat->header.sectors_per_fat_32 * fat->header.base.number_of_fats)) * fat->header.base.bytes_per_sector;
if (offset_in_cluster + buffer_size >= cluster_size) {
return 0;
}
os_u32 cluster_offset = data_offset + ((cluster - 2) * cluster_size) + offset_in_cluster;
if(fat->handle.seek(cluster_offset, LIBFAT_SEEK_ORIGIN, fat->handle.user_data) != OS_TRUE) {
return 0;
}
os_u32 written = fat->handle.write(buffer_size, buffer, fat->handle.user_data);
return written;
}
os_bool libfat_open(FatControlBlock* fat, LibFatDirectoryEntry* entry, LibFatFile* result) {
if(result == 0 || fat == 0 || entry == 0) {
return OS_FALSE;
}
if ((entry->attribute & FAT_SYSTEM_BIT) != 0 ||
(entry->attribute & FAT_VOLUME_BIT) != 0) {
if ((entry->entry.attribute & FAT_SYSTEM_BIT) != 0 ||
(entry->entry.attribute & FAT_VOLUME_BIT) != 0) {
return OS_FALSE;
}
result->fat = fat;
result->file_entry = *entry;
result->fat_cluster_size = fat->header.base.sectors_per_cluster * fat->header.base.bytes_per_sector;
result->fat_data_offset = (fat->header.base.reserved_sectors + (fat->header.sectors_per_fat_32 * fat->header.base.number_of_fats)) * fat->header.base.bytes_per_sector;
result->position = 0;
result->current_cluster = (((os_u32)entry->start_cluster_high) << 16) + entry->start_cluster;
result->current_cluster = (((os_u32)entry->entry.start_cluster_high) << 16) + entry->entry.start_cluster;
result->in_cluster_position = 0;
return OS_TRUE;
}
os_bool libfat_open_directory(FatControlBlock* fat, FatDirectoryEntry* entry, LibFatDirectory* result) {
os_bool libfat_open_directory(FatControlBlock* fat, LibFatDirectoryEntry* entry, LibFatDirectory* result) {
if (fat == 0 || result == 0) {
return OS_FALSE;
}
if (entry != 0 && (entry->attribute & FAT_SUBDIRECTORY_BIT) == 0) {
if (entry != 0 && (entry->entry.attribute & FAT_SUBDIRECTORY_BIT) == 0) {
return OS_FALSE;
}
result->fat = fat;
result->fat_cluster_size = fat->header.base.sectors_per_cluster * fat->header.base.bytes_per_sector;
result->current_cluster = entry == 0 ? fat->header.first_root_cluster : (((os_u32)entry->start_cluster_high) << 16) + entry->start_cluster;
result->current_cluster = entry == 0 ? fat->header.first_root_cluster : (((os_u32)entry->entry.start_cluster_high) << 16) + entry->entry.start_cluster;
result->base_cluster = result->current_cluster;
result->position_in_cluster = 0;
result->done = 0;
@ -138,7 +175,7 @@ os_bool libfat_open_directory(FatControlBlock* fat, FatDirectoryEntry* entry, Li
return OS_TRUE;
}
os_bool libfat_read_directory(LibFatDirectory* dir, FatDirectoryEntry* entry) {
os_bool libfat_read_directory(LibFatDirectory* dir, LibFatDirectoryEntry* entry) {
if (dir == 0 || entry == 0) {
return OS_FALSE;
}
@ -149,12 +186,15 @@ os_bool libfat_read_directory(LibFatDirectory* dir, FatDirectoryEntry* entry) {
FatDirectoryEntry my_entry;
os_u32 read = libfat_load_cluster(dir->fat, dir->current_cluster, &my_entry, sizeof(FatDirectoryEntry), dir->position_in_cluster);
os_u32 cluster = dir->current_cluster;
os_u32 offset = dir->position_in_cluster;
dir->position_in_cluster += read;
if (dir->position_in_cluster == dir->fat_cluster_size) {
os_u32 next_cluster = libfat_read_cluster(dir->fat, dir->current_cluster);
if (next_cluster >= FAT_LAST_CLUSTER_32) {
dir->done = OS_TRUE;
}
dir->current_cluster = next_cluster;
}
if (my_entry.file_name[0] == '\0') {
@ -162,15 +202,17 @@ os_bool libfat_read_directory(LibFatDirectory* dir, FatDirectoryEntry* entry) {
return OS_FALSE;
}
*entry = my_entry;
entry->entry = my_entry;
entry->entry_cluster = cluster;
entry->entry_offset = offset;
return OS_TRUE;
}
os_u32 libfat_read(LibFatFile* file, void* buffer, os_u32 buffer_size) {
os_u32 read = 0;
os_bool eof = file->position >= file->file_entry.file_size ? OS_TRUE : OS_FALSE;
os_bool eof = file->position >= file->file_entry.entry.file_size ? OS_TRUE : OS_FALSE;
while(read < buffer_size && eof != OS_TRUE) {
os_u32 amount_left = file->file_entry.file_size - file->position;
os_u32 amount_left = file->file_entry.entry.file_size - file->position;
os_u32 amount_to_read = (buffer_size - read) > amount_left ? amount_left : buffer_size - read;
os_u32 local_read;
@ -191,7 +233,7 @@ os_u32 libfat_read(LibFatFile* file, void* buffer, os_u32 buffer_size) {
file->in_cluster_position = 0;
}
if (file->position == file->file_entry.file_size) {
if (file->position == file->file_entry.entry.file_size) {
eof = OS_TRUE;
}
}
@ -224,6 +266,282 @@ os_bool libfat_init(FileHandle file, void* buffer, os_u32 buffer_size, FatContro
return OS_TRUE;
}
os_bool libfat_seek(LibFatFile* file, os_s32 position, os_u32 direction) {
if (direction != LIBFAT_SEEK_CURRENT && direction != LIBFAT_SEEK_END && direction != LIBFAT_SEEK_ORIGIN) {
return OS_FALSE;
}
if (file == 0) {
return OS_FALSE;
}
os_u32 target = 0;
os_s32 final = 0;
os_s32 reverse = 0;
switch(direction) {
case LIBFAT_SEEK_ORIGIN:
target = (os_u32)position;
break;
case LIBFAT_SEEK_CURRENT:
final = position + file->position;
if (final < 0) {
return OS_FALSE;
}
target = (os_u32)final;
break;
case LIBFAT_SEEK_END:
reverse = file->file_entry.entry.file_size - position;
if (reverse < 0) {
return OS_FALSE;
}
target = (os_u32)reverse;
break;
}
if (target >= file->file_entry.entry.file_size) {
return OS_FALSE;
}
os_u32 cluster = (((os_u32)file->file_entry.entry.start_cluster_high) << 16) + file->file_entry.entry.start_cluster;
os_u32 tmp_pos = 0;
while((tmp_pos + file->fat_cluster_size) <= target) {
os_u32 next_cluster = libfat_read_cluster(file->fat, cluster);
tmp_pos += file->fat_cluster_size;
cluster = next_cluster;
}
file->current_cluster = cluster;
file->in_cluster_position = target - tmp_pos;
file->position = target;
return OS_TRUE;
}
os_u32 libfat_find_free_cluster(FatControlBlock* fat) {
os_u32 cluster_id = 2;
os_u32 cluster_value = FAT_LAST_CLUSTER_32;
do {
cluster_value = libfat_read_cluster(fat, cluster_id);
if (cluster_value != 0) {
cluster_id++;
}
if (cluster_id >= (fat->header.sectors_per_fat_32 * fat->header.base.bytes_per_sector) / sizeof(os_u32)) {
return 0;
}
} while(cluster_value != 0);
return cluster_id;
}
os_bool libfat_fsinfo_update(FatControlBlock* fat) {
os_u32 fsinfo_offset = fat->header.fsinfo_sector * fat->header.base.bytes_per_sector;
if(fat->handle.seek(fsinfo_offset, LIBFAT_SEEK_ORIGIN, fat->handle.user_data) != OS_TRUE) {
return OS_FALSE;
}
os_u32 sig = 0;
os_u32 read = fat->handle.read(sizeof(os_u32), (void*)&sig, fat->handle.user_data);
if (read != sizeof(os_u32) || sig != FAT_FSINFO_SIG_0) {
return OS_FALSE;
}
if(fat->handle.seek(fsinfo_offset + 484, LIBFAT_SEEK_ORIGIN, fat->handle.user_data) != OS_TRUE) {
return OS_FALSE;
}
read = fat->handle.read(sizeof(os_u32), (void*)&sig, fat->handle.user_data);
if (read != sizeof(os_u32) || sig != FAT_FSINFO_SIG_1) {
return OS_FALSE;
}
os_u32 free_clusters = 0;
read = fat->handle.read(sizeof(os_u32), (void*)&free_clusters, fat->handle.user_data);
if (read != sizeof(os_u32)) {
return OS_FALSE;
}
os_u32 next_free_cluster = 0;
read = fat->handle.read(sizeof(os_u32), (void*)&next_free_cluster, fat->handle.user_data);
if (read != sizeof(os_u32)) {
return OS_FALSE;
}
if (free_clusters != 0xffffffff) {
free_clusters--;
if(fat->handle.seek(fsinfo_offset + 488, LIBFAT_SEEK_ORIGIN, fat->handle.user_data) == OS_TRUE) {
fat->handle.write(sizeof(os_u32), (void*)&free_clusters, fat->handle.user_data);
}
}
if (next_free_cluster != 0xffffffff) {
next_free_cluster = libfat_find_free_cluster(fat);
if (next_free_cluster < 2) {
next_free_cluster = 0xffffffff;
}
if (fat->handle.seek(fsinfo_offset + 492, LIBFAT_SEEK_ORIGIN, fat->handle.user_data) == OS_TRUE) {
fat->handle.write(sizeof(os_u32), (void*)&next_free_cluster, fat->handle.user_data);
}
}
return OS_TRUE;
}
os_u32 libfat_add_cluster_to_chain(FatControlBlock* fat, os_u32 last_cluster_id) {
os_u32 cluster_value;
do {
cluster_value = libfat_read_cluster(fat, last_cluster_id);
if(cluster_value == 0) {
return 0;
}
} while(cluster_value < FAT_LAST_CLUSTER_32);
os_u32 free_cluster = libfat_find_free_cluster(fat);
if (free_cluster == 0) {
return 0;
}
if(libfat_write_fat_cluster(fat, last_cluster_id, free_cluster) != OS_TRUE) {
return 0;
}
if(libfat_write_fat_cluster(fat, free_cluster, FAT_LAST_CLUSTER_32_2) != OS_TRUE) {
return 0;
}
libfat_fsinfo_update(fat);
return free_cluster;
}
os_bool libfat_add_entry_to_directory(FatControlBlock* fat, LibFatDirectoryEntry* parent, FatDirectoryEntry* entry, LibFatDirectoryEntry* result) {
os_u32 cluster = fat->header.first_root_cluster;
if (parent != 0) {
cluster = (((os_u32)parent->entry.start_cluster_high) << 16) + parent->entry.start_cluster;
}
os_u32 cluster_offset = 0;
os_u32 next_cluster = libfat_read_cluster(fat, cluster);
FatDirectoryEntry local_entry;
do {
os_u32 read = libfat_load_cluster(fat, cluster, (void*)&local_entry, sizeof(FatDirectoryEntry), cluster_offset);
if (local_entry.file_name[0] == '\0') {
break;
}
cluster_offset += read;
if (cluster_offset >= fat->header.base.sectors_per_cluster * fat->header.base.bytes_per_sector) {
cluster_offset = 0;
if (next_cluster >= FAT_LAST_CLUSTER_32) {
next_cluster = libfat_add_cluster_to_chain(fat, next_cluster);
if (next_cluster == 0) {
//Invalid end cluster or no more available clusters
return OS_FALSE;
}
}
cluster = next_cluster;
next_cluster = libfat_read_cluster(fat, cluster);
break;
}
} while(local_entry.file_name[0] != '\0');
if(libfat_write_cluster(fat, cluster, (void*)entry, sizeof(FatDirectoryEntry), cluster_offset) == 0) {
return OS_FALSE; //TODO: Maybe undo added cluster
}
result->entry_cluster = cluster;
result->entry_offset = cluster_offset;
result->entry = *entry;
cluster_offset += sizeof(FatDirectoryEntry);
if (cluster_offset >= fat->header.base.bytes_per_sector * fat->header.base.sectors_per_cluster) {
cluster = libfat_add_cluster_to_chain(fat, cluster);
cluster_offset = 0;
}
char buffer[sizeof(FatDirectoryEntry)];
for(int i = 0; i < sizeof(FatDirectoryEntry); i++) {
buffer[i] = '\0';
}
libfat_write_cluster(fat, cluster, (void*)buffer, sizeof(FatDirectoryEntry), cluster_offset);
return OS_TRUE;
}
os_bool libfat_create(FatControlBlock* fat, LibFatDirectoryEntry* parent_entry, os_s8* name, os_bool directory, LibFatDirectoryEntry* result) {
FatDirectoryEntry new_entry;
for(int i = 0; i < 8; i++) {
new_entry.file_name[i] = name[i];
}
for(int i = 0; i < 3; i++) {
new_entry.extension[i] = name[8 + i];
}
new_entry.attribute = directory != OS_FALSE ? FAT_SUBDIRECTORY_BIT : 0;
new_entry.date = 0;
for(int i = 0; i < 8; i++) {
new_entry.reserved[i] = 0;
}
new_entry.time = 0;
new_entry.file_size = 0;
os_u32 cluster = libfat_find_free_cluster(fat);
if (cluster < 2) {
return OS_FALSE;
}
new_entry.start_cluster = (os_u16) cluster;
new_entry.start_cluster_high = (os_u16) (cluster >> 16);
if (libfat_write_fat_cluster(fat, cluster, FAT_LAST_CLUSTER_32_2) != OS_TRUE) {
return OS_FALSE;
}
if(libfat_add_entry_to_directory(fat, parent_entry, &new_entry, result) != OS_TRUE) {
libfat_write_fat_cluster(fat, cluster, 0);
return OS_FALSE;
}
libfat_fsinfo_update(fat);
return OS_TRUE;
}
os_u32 libfat_write(LibFatFile* f, void* buffer, os_u32 buffer_size) {
if (f == 0 || buffer == 0 || buffer_size == 0) {
return 0;
}
os_u32 start_position = f->position;
os_u32 written = 0;
while (buffer_size > 0) {
os_u32 amount = f->fat_cluster_size - f->in_cluster_position;
if (amount > buffer_size) {
amount = buffer_size;
}
os_u32 w = libfat_write_cluster(f->fat, f->current_cluster, buffer, amount, f->in_cluster_position);
written += w;
f->position += w;
f->in_cluster_position += w;
buffer += w;
buffer_size -= w;
if (f->in_cluster_position >= f->fat_cluster_size) {
f->in_cluster_position = 0;
os_u32 next = libfat_read_cluster(f->fat, f->current_cluster);
if (next >= FAT_LAST_CLUSTER_32_2) {
next = libfat_add_cluster_to_chain(f->fat, next);
}
f->current_cluster = next;
}
}
if(f->position > f->file_entry.entry.file_size) {
f->file_entry.entry.file_size = f->position;
libfat_write_cluster(f->fat, f->file_entry.entry_cluster, (void*)&f->file_entry.entry, sizeof(FatDirectoryEntry), f->file_entry.entry_offset);
}
return written;
}
void libfat_test(FileHandle handle, PrintRoutine print, PrintNumber printNumber) {
FatControlBlock cb;
if (libfat_init(handle, loaded_fat_segment, 512 * sizeof(os_u32), &cb) != OS_TRUE) {
@ -237,29 +555,31 @@ void libfat_test(FileHandle handle, PrintRoutine print, PrintNumber printNumber)
return;
}
FatDirectoryEntry entry;
os_bool any = OS_FALSE;
LibFatDirectoryEntry entry;
while(libfat_read_directory(&dir, &entry) == OS_TRUE) {
if ((entry.attribute & (os_s8)FAT_HIDDEN_BIT) != 0 ||
(entry.attribute & (os_s8)FAT_VOLUME_BIT) != 0 ||
(entry.attribute & (os_s8)FAT_SYSTEM_BIT) != 0) {
if ((entry.entry.attribute & (os_s8)FAT_HIDDEN_BIT) != 0 ||
(entry.entry.attribute & (os_s8)FAT_VOLUME_BIT) != 0 ||
(entry.entry.attribute & (os_s8)FAT_SYSTEM_BIT) != 0) {
continue;
}
any = OS_TRUE;
print("Entry name: ", 0);
print(entry.file_name, 11);
print(entry.entry.file_name, 11);
os_u32 cluster = (((os_u32)entry.start_cluster_high) << 16) + entry.start_cluster;
os_u32 cluster = (((os_u32)entry.entry.start_cluster_high) << 16) + entry.entry.start_cluster;
print("Cluster: ", 0);
printNumber(cluster);
print("Size: ", 0);
printNumber(entry.file_size);
printNumber(entry.entry.file_size);
os_u32 effective_size = entry.file_size > 512 ? 512 : entry.file_size;
os_u32 effective_size = entry.entry.file_size > 512 ? 512 : entry.entry.file_size;
if(effective_size > 0) {
LibFatFile f;
if (libfat_open_read(&cb, &entry, &f) == OS_TRUE) {
if (libfat_open(&cb, &entry, &f) == OS_TRUE) {
char buffer[512];
os_u32 amount = libfat_read(&f, buffer, 512);
print("Content: ", 0);
@ -269,4 +589,19 @@ void libfat_test(FileHandle handle, PrintRoutine print, PrintNumber printNumber)
print("--------", 0);
}
if(any == OS_FALSE) {
LibFatDirectoryEntry created_file;
libfat_create(&cb, 0, "TEST TXT", OS_FALSE, &created_file);
print("Added file 'test.txt'", 0);
LibFatFile new_file;
if(libfat_open(&cb, &created_file, &new_file) != OS_TRUE) {
print("Failed to open new file", 0);
return;
}
char* data = "test";
libfat_write(&new_file, data, 5);
}
}

View file

@ -8,7 +8,9 @@ _main:
JMP entry
; FAT32 Header.
global fat_header
fat_header: times 87 db 0
fat_header:
dw 0x4949
times 85 db 0
; function READ_SECTORS_EXTENDED: Read sectors from disk
; Uses INT 13h AH=42h from: http://www.ctyme.com/intr/rb-0708.htm