OSDev.org https://forum.osdev.org/ |
|
Assembly + INT 13 AH 42 https://forum.osdev.org/viewtopic.php?f=13&t=25807 |
Page 1 of 1 |
Author: | mark3094 [ Fri Sep 14, 2012 11:27 pm ] |
Post subject: | Assembly + INT 13 AH 42 |
I've been working on my Kernel, but I've had to take a step back to look at my bootloader. I have found out that my bootloader can load a 40KB kernel, but hangs if it tries to load anything over 40KB. I am using INT 13, AH=42 in real mode to read from a FAT32 partition. I read the kernel to 0000:5500 After the jump to protected mode, the boot loader copies the kernel from 0x5500 to 0x100000 I have found that if the kernel is larger than 40KB, it will not fit into the real mode segment that I am using as the INT 13 buffer. I have considered using 0550:0000 as the buffer (same physical memory location), which would give me up to 64KB for the Kernel before the segment is full, however, (1) I can't get this to work, and (2) I'll probably hit the limit for this again sometime in the near future. I figure I can use 0550:0000 as the buffer, and when it gets full, move to the next segment. However, as I've said, I can't get it to work. This is the DAP I'm using: Code: DAP: .Size DB 0x10 .NULL DB 0x00 .Sectors DW 0x00 .Offset DW 0x00 .Segment DW 0x00 .LBA DD 0x00 .LBA48 DD 0x00 If I use code like this, it works: Code: mov word [DAP.Segment], 0x0000 mov word [DAP.Offset], 0x5500 If I change it, I get problems: Code: mov word [DAP.Segment], 0x0550 mov word [DAP.Offset], 0x0000 I'm using VMWare Player to test with. Any ideas what I may be doing wrong here? |
Author: | Brendan [ Sat Sep 15, 2012 12:03 am ] |
Post subject: | Re: Assembly + INT 13 AH 42 |
Hi, mark3094 wrote: I have found that if the kernel is larger than 40KB, it will not fit into the real mode segment that I am using as the INT 13 buffer. If the kernel is larger than 64 KiB, then you have to split it into multiple reads (where each read is less than 64 KiB). If the kernel is larger than about 600 KiB (e.g. Linux is typically about 5 MiB) then you need a loop that reads (up to) 64 KiB then copies it somewhere else (e.g. to 0x00100000). Also, for FAT32 the file may be fragmented, and you'd have to deal with that too. The simplest way would be something like: Code: while(not_all_loadeed) { find_next_cluster(); read_cluster_into_buffer(); copy_cluster_to_memory_above_0x00100000(); } You can improve performance a little by reading more than one cluster at a time (where possible): Code: while(not_all_loadeed) { find_next_cluster(); sectors = find_contiguous_clusters() * sectors_per_cluster; if(sectors > buffer_size / bytes_per_sector) { sectors = buffer_size / bytes_per_sector; } read_contiguous_sectors_into_buffer(count); copy_sectors_to_memory_above_0x00100000(count); } Also, for the last cluster in the file you may be able to skip some sectors. For example, if a cluster is 2 KiB (4 sectors) and the end of the file only consumes 123 bytes of the last cluster, then you could only load 1 sector of the last cluster. mark3094 wrote: Any ideas what I may be doing wrong here? Not really. 0x0550:0x0000 is the same physical address as 0x0000:0x5500, and there's no other information that we can check. Cheers, Brendan |
Author: | mark3094 [ Sat Sep 15, 2012 1:12 am ] |
Post subject: | Re: Assembly + INT 13 AH 42 |
I have found out why I was having problems with the Segment:Offset, and that is because another function was overwriting some values. I have put in some PUSH and POPs, and solved that part. However, my Kernel still won't load if it's over 40KB. It seems to hang when INT 13 is called the 11th time (8 sectors per cluster, one read for each cluster, iw 4KB per INT 13). Any thoughts on how I can troubleshoot this? I tried to read AH after INT is used, but it has already hung, so I can't print it to screen. EDIT: I have found that this problem happens as soon as I try to write 4KB to 0550:A000 (0xF500 linear). Does this overwrite reserved memory? As far as I can see I don't have anything loaded there. Stage 2 is at 0x0500 Kernel (attempting) at 0x5500 Stack at 0x0050 Memory map at 0x3500 FAT/RD/etc at 0x2500 Can't see anything on the Wiki either http://wiki.osdev.org/Memory_Map_%28x86%29 EDIT 2: I have also found that I can use INT 13h AH 42h to store sectors in memory addresses up to 0x10499 (linear). As soon as I write to 0x104A0, it hangs or faults. Any idea what this means? |
Author: | Brendan [ Sat Sep 15, 2012 4:23 am ] |
Post subject: | Re: Assembly + INT 13 AH 42 |
Hi, Is this right? Code: 0x0050 to 0x04FF is Stack 0x0500 to 0x14FF is Stage 2 0x2500 to 0x34FF is FAT/RD/etc 0x3500 to 0x54FF is Memory map 0x5500 to ?????? is kernel Now look at the first 4 rows of the memory map at http://wiki.osdev.org/Memory_Map_%28x86%29, and rearrange it a little: Code: 0x0000 to 0x03FF is Real Mode IVT (Interrupt Vector Table) 0x0400 to 0x04FF is BDA (BIOS data area) 0x0500 to ?????? is Conventional memory Now, let's merge these into one: Code: 0x0050 to 0x04FF is Real Mode IVT that is TRASHED BY YOUR STACK 0x0400 to 0x04FF is BDA (BIOS data area) that is TRASHED BY YOUR STACK 0x0500 to 0x14FF is Stage 2 0x2500 to 0x34FF is FAT/RD/etc 0x3500 to 0x54FF is Memory map 0x5500 to ?????? is kernel Cheers, Brendan |
Author: | mark3094 [ Sat Sep 15, 2012 4:33 am ] |
Post subject: | Re: Assembly + INT 13 AH 42 |
Sorry, my mistake, my stack is not at 0x50, it is at 0xFFFF (not sure why I said 0x50... ) Anyway, it appears I am trashing my stack with my Kernel, which is very bad of course. I tried loading at 0x11000, and it worked just fine. Thanks again for your help. Much appreciated |
Page 1 of 1 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |