📄 ext2.asm
字号:
Done:
mov al,0dh
call PutCharsCallBios
mov al,0ah
call PutCharsCallBios
retn
msgDiskError db 'Disk error',0
; Sorry, need the space...
;msgAnyKey db 'Press any key to restart',0
msgAnyKey db 'Press any key',0
times 509-($-$$) db 0 ; Pad to 509 bytes
BootPartition db 0
dw 0aa55h ; BootSector signature
; End of bootsector
;
; Now starts the extra boot code that we will store
; at sector 1 on a EXT2 volume
LoadRootDirectory:
mov eax,EXT2_ROOT_INO ; Put the root directory inode number in EAX
call Ext2ReadInode ; Read in the inode
; Point ES:DI to the inode structure at 6000:8000
push WORD 6000h
pop es
mov di,8000h
push di
push es ; Save these for later
; Get root directory size from inode structure
mov eax,DWORD [es:di+4]
push eax
; Now that the inode has been read in load
; the root directory file data to 0000:8000
call Ext2ReadEntireFile
; Since the root directory was loaded to 0000:8000
; then add 8000h to the root directory's size
pop eax
mov edx,8000h ; Set EDX to the current offset in the root directory
add eax,edx ; Initially add 8000h to the size of the root directory
SearchRootDirectory:
push edx ; Save current offset in root directory
push eax ; Save the size of the root directory
; Now we have to convert the current offset
; in the root directory to a SEGMENT:OFFSET pair
mov eax,edx
xor edx,edx
mov ecx,16
div ecx ; Now AX:DX has segment & offset
mov es,ax
mov di,dx
push di ; Save the start of the directory entry
add di,byte 8 ; Add the offset to the filename
mov si,filename
mov cl,11
rep cmpsb ; Compare the file names
pop di
pop eax
pop edx
jz FoundFile
; Nope, didn't find it in this entry, keep looking
movzx ecx,WORD [es:di+4]
add edx,ecx
; Check to see if we have reached the
; end of the root directory
cmp edx,eax
jb SearchRootDirectory
jmp PrintFileNotFound
FoundFile:
mov eax,[es:di] ; Get inode number from directory entry
call Ext2ReadInode ; Read in the inode
; Point ES:DI to the inode structure at 6000:8000
pop es
pop di ; These were saved earlier
mov cx,[es:di] ; Get the file mode so we can make sure it's a regular file
and ch,EXT2_S_IFMT ; Mask off everything but the file type
cmp ch,EXT2_S_IFREG ; Make sure it's a regular file
je LoadFreeLoader
jmp PrintRegFileError
LoadFreeLoader:
mov si,msgLoading ; "Loading FreeLoader..." message
call PutChars ; Display it
call Ext2ReadEntireFile ; Read freeldr.sys to 0000:8000
mov dl,[BYTE bp+BootDrive]
mov dh,[BYTE bp+BootPartition]
push byte 0 ; We loaded at 0000:8000
push WORD 8000h ; We will do a far return to 0000:8000h
retf ; Transfer control to FreeLoader
; Reads ext2 file data into [0000:8000]
; This function assumes that the file's
; inode has been read in to 6000:8000 *and*
; ES:DI points to 6000:8000
; This will load all the blocks up to
; and including the double-indirect pointers.
; This should be sufficient because it
; allows for ~64MB which is much bigger
; than we need for a boot loader.
Ext2ReadEntireFile:
; Reset the load segment
mov WORD [BYTE bp+Ext2ReadEntireFileLoadSegment],800h
; Now we must calculate how
; many blocks to read in
; We will do this by rounding the
; file size up to the next block
; size and then dividing by the block size
mov eax,DWORD [BYTE bp+Ext2BlockSizeInBytes] ; Get the block size in bytes
push eax
dec eax ; Ext2BlockSizeInBytes -= 1
add eax,DWORD [es:di+4] ; Add the file size
xor edx,edx
pop ecx ; Divide by the block size in bytes
div ecx ; EAX now contains the number of blocks to load
push eax
; Make sure the file size isn't zero
cmp eax,byte 0
jnz Ext2ReadEntireFile2
jmp PrintFileSizeError
Ext2ReadEntireFile2:
; Save the indirect & double indirect pointers
mov edx,DWORD [es:di+0x58] ; Get indirect pointer
mov [BYTE bp+Ext2InodeIndirectPointer],edx ; Save indirect pointer
mov edx,DWORD [es:di+0x5c] ; Get double indirect pointer
mov [BYTE bp+Ext2InodeDoubleIndirectPointer],edx ; Save double indirect pointer
; Now copy the direct pointers to 7000:0000
; so that we can call Ext2ReadDirectBlocks
push ds ; Save DS
push es
push WORD 7000h
pop es
pop ds
mov si,8028h
xor di,di ; DS:SI = 6000:8028 ES:DI = 7000:0000
mov cx,24 ; Moving 24 words of data
rep movsw
pop ds ; Restore DS
; Now we have all the block pointers in the
; right location so read them in
pop eax ; Restore the total number of blocks in this file
xor ecx,ecx ; Set the max count of blocks to read to 12
mov cl,12 ; which is the number of direct block pointers in the inode
call Ext2ReadDirectBlockList
; Check to see if we actually have
; blocks left to read
cmp eax,byte 0
jz Ext2ReadEntireFileDone
; Now we have read all the direct blocks in
; the inode. So now we have to read the indirect
; block and read all it's direct blocks
push eax ; Save the total block count
mov eax,DWORD [BYTE bp+Ext2InodeIndirectPointer] ; Get the indirect block pointer
push WORD 7000h
pop es
xor bx,bx ; Set the load address to 7000:0000
call Ext2ReadBlock ; Read the block
; Now we have all the block pointers from the
; indirect block in the right location so read them in
pop eax ; Restore the total block count
mov ecx,DWORD [BYTE bp+Ext2PointersPerBlock] ; Get the number of block pointers that one block contains
call Ext2ReadDirectBlockList
; Check to see if we actually have
; blocks left to read
cmp eax,byte 0
jz Ext2ReadEntireFileDone
; Now we have read all the direct blocks from
; the inode's indirect block pointer. So now
; we have to read the double indirect block
; and read all it's indirect blocks
; (whew, it's a good thing I don't support triple indirect blocks)
mov [BYTE bp+Ext2BlocksLeftToRead],eax ; Save the total block count
mov eax,DWORD [BYTE bp+Ext2InodeDoubleIndirectPointer] ; Get the double indirect block pointer
push WORD 7800h
pop es
push es ; Save an extra copy of this value on the stack
xor bx,bx ; Set the load address to 7000:8000
call Ext2ReadBlock ; Read the block
pop es ; Put 7800h into ES (saved on the stack already)
xor di,di
Ext2ReadIndirectBlock:
mov eax,DWORD [es:di] ; Get indirect block pointer
add di,BYTE 4 ; Update DI for next array index
push es
push di
push WORD 7000h
pop es
xor bx,bx ; Set the load address to 7000:0000
call Ext2ReadBlock ; Read the indirect block
; Now we have all the block pointers from the
; indirect block in the right location so read them in
mov eax,DWORD [BYTE bp+Ext2BlocksLeftToRead] ; Restore the total block count
mov ecx,DWORD [BYTE bp+Ext2PointersPerBlock] ; Get the number of block pointers that one block contains
call Ext2ReadDirectBlockList
mov [BYTE bp+Ext2BlocksLeftToRead],eax ; Save the total block count
pop di
pop es
; Check to see if we actually have
; blocks left to read
cmp eax,byte 0
jnz Ext2ReadIndirectBlock
Ext2ReadEntireFileDone:
ret
; Reads a maximum number of blocks
; from an array at 7000:0000
; and updates the total count
; ECX contains the max number of blocks to read
; EAX contains the number of blocks left to read
; On return:
; EAX contians the new number of blocks left to read
Ext2ReadDirectBlockList:
cmp eax,ecx ; Compare it to the maximum number of blocks to read
ja CallExt2ReadDirectBlocks ; If it will take more blocks then just read all of the blocks
mov cx,ax ; Otherwise adjust the block count accordingly
CallExt2ReadDirectBlocks:
sub eax,ecx ; Subtract the number of blocks being read from the total count
push eax ; Save the new total count
call Ext2ReadDirectBlocks
pop eax ; Restore the total count
ret
; Reads a specified number of blocks
; from an array at 7000:0000
; CX contains the number of blocks to read
Ext2ReadDirectBlocks:
push WORD 7000h
pop es
xor di,di ; Set ES:DI = 7000:0000
Ext2ReadDirectBlocksLoop:
mov eax,[es:di] ; Get direct block pointer from array
add di,BYTE 4 ; Update DI for next array index
push cx ; Save number of direct blocks left
push es ; Save array segment
push di ; Save array offset
mov es,[BYTE bp+Ext2ReadEntireFileLoadSegment]
xor bx,bx ; Setup load address for next read
call Ext2ReadBlock ; Read the block (this updates ES for the next read)
mov [BYTE bp+Ext2ReadEntireFileLoadSegment],es ; Save updated ES
pop di ; Restore the array offset
pop es ; Restore the array segment
pop cx ; Restore the number of blocks left
loop Ext2ReadDirectBlocksLoop
; At this point all the direct blocks should
; be loaded and ES (Ext2ReadEntireFileLoadSegment)
; should be ready for the next read.
ret
; Displays a file not found error message
; And reboots
PrintFileNotFound:
mov si,msgFreeLdr ; FreeLdr not found message
jmp short DisplayItAndReboot
; Displays a file size is 0 error
; And reboots
PrintFileSizeError:
mov si,msgFileSize ; Error message
jmp short DisplayItAndReboot
; Displays a file is not a regular file error
; And reboots
PrintRegFileError:
mov si,msgRegFile ; Error message
DisplayItAndReboot:
call PutChars ; Display it
jmp Reboot
msgFreeLdr db 'freeldr.sys not found',0
msgFileSize db 'File size is 0',0
msgRegFile db 'freeldr.sys isnt a regular file',0
filename db 'freeldr.sys'
msgLoading db 'Loading FreeLoader...',0
times 1022-($-$$) db 0 ; Pad to 1022 bytes
dw 0aa55h ; BootSector signature
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -