OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 12:22 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Assembly + INT 13 AH 42
PostPosted: Fri Sep 14, 2012 11:27 pm 
Offline
Member
Member
User avatar

Joined: Mon Feb 14, 2011 10:32 pm
Posts: 164
Location: Australia
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?


Top
 Profile  
 
 Post subject: Re: Assembly + INT 13 AH 42
PostPosted: Sat Sep 15, 2012 12:03 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
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

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: Assembly + INT 13 AH 42
PostPosted: Sat Sep 15, 2012 1:12 am 
Offline
Member
Member
User avatar

Joined: Mon Feb 14, 2011 10:32 pm
Posts: 164
Location: Australia
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?


Top
 Profile  
 
 Post subject: Re: Assembly + INT 13 AH 42
PostPosted: Sat Sep 15, 2012 4:23 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
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

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: Assembly + INT 13 AH 42
PostPosted: Sat Sep 15, 2012 4:33 am 
Offline
Member
Member
User avatar

Joined: Mon Feb 14, 2011 10:32 pm
Posts: 164
Location: Australia
Sorry, my mistake, my stack is not at 0x50, it is at 0xFFFF (not sure why I said 0x50... #-o )

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


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 27 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group