On the EOS codebase, bootloader file I/O functions can be called before you jump to main firmware, and main firmware file I/O can be called after the card is mounted (pretty late in the boot process). They can't be mixed - it locks up.
I'm not sure how it's done on CHDK - I see DISKBOOT.BIN referenced in two places: FC0005CC (Rescue Loader) and FC0637B2 (StartDiskboot, main firmware).
If you are running the debug shell, I guess DISKBOOT.BIN was loaded with the first method; in this case, you can probably call these functions:
FC0008A4 int mount_sd_card(void)
FC00257C int sd_load_file(int drive_maybe, char* filename, void* buffer, int unknown, int* out_file_size) // high-level function, e.g. sd_load_file(0, "DISKBOOT.BIN", 0x40008000, 0x5FC00000, &diskboot_size);
FC0008F4 sd_read_sector(int drive_maybe, int start_sector, int num_sectors, void* buffer) // low-level sector read function (512 bytes at a time)
If not, I guess DISKBOOT.BIN is loaded with the second method, and here I'm afraid you need to wait for the file I/O backend to get initialized. Or you might be lucky called the bootloader functions, not sure.
BTW, the latest QEMU is able to emulate file I/O on 80D bootloader, both read and write (also digic 6), so implementing this on
M3 should be doable. Then we can find the answer to your question 😀