Yeah, that's sort of a big portion of the problem. It must be a real CD/DVD image, no floppy emulation. It's a basic design requirement, and the final target of this physically requires it. I wish I could elaborate, but I'm keeping my end goal under wraps for the time being. But I've got to learn how all this works before I can do any serious planning for the real thing.
I have the Singularity RDK from Microsoft, which you might know, is a managed operating system/kernel implemented mainly in C#. Looking through the source, I found one ASM file which looks like it's geared in the same direction I'm trying to go. It can't be compiled with Nasm, and I don't know enough about all of this to hope to translate it. So I'm going to post it here and see if you guys can make heads or tails out of it.
(EDIT: And NO, I'm NOT trying to make a managed OS, lol. Not even a desktop OS for that matter.)
Sorry I have to post this since it won't allow me to attach any extension:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Copyright (c) Microsoft Corporation. All rights reserved.
;;
;;;;;;;;;;;;;;;;;;;;
; Concerns
; 1 - there is no error checking on the int13 calls
; 2 - we assume that the block size is 2048 bytes
; 3 - this cannot handle large root directories (>64KB)
;;;;;;;;;;;;;;;;;;;;
; Constants
BootSecOrigin EQU 07c00h ; the BIOS puts the boot sector at 07c0h:0000 == 0000:7c00h
StackOffset EQU -12 ; we will put the stack a small bit below it (we hardly use the stack, so it is safe...)
;;;;;;;;;;;;;;;;;;;;
; Macros
JMPF16 MACRO SEG:REQ,OFF:REQ
db 0eah
dw OFF
dw SEG
ENDM
;;;;;;;;;;;;;;;;;;;;
; Directives
.model tiny
.686p
;;;;;;;;;;;;;;;;;;;;
; Begin Code segment
_TEXT SEGMENT use16 ; 16-bit code segment
.code
ORG 0h ; ETFS puts us at 07c0h:0000
start:
JMPF16 07c0h,OFFSET Step1
Step1: ; set stack and data segments
mov cx, cs
mov ss, cx
mov sp, BootSecOrigin + StackOffset
mov es, cx
mov ds, cx
mov bp, sp
Step2: ; Save the boot drive (dl holds it on boot)
mov [CDDrive], dl
Step3: ; Clear the Screen
mov ax, 02h
int 010h
;; Configure GS to point to the text-mode video console.
mov ax, 0b800h
mov gs, ax
;; Write 'A' to position 0.
mov ax, 04f41h
mov gs:[0], ax
;; Write 'B' to position 1.
mov ax, 04f42h
mov gs:[2], ax
Step4: ; Load the PVD to get the Logical Block Size
mov eax, 10h ; the PVD is in the 16th block
mov bx, 2000h
mov es, bx ; transfer address = 2000:0000
mov cx, 1
call ReadDisk
mov ax, es:128 ; block size is at offset 128
mov [BlockSize], ax
;; Write 'C' to position 2.
mov ax, 04f43h
mov gs:[4], ax
Step5: ; Find the Joliet SVD, and then find the Root Directory Information
mov eax, 10h ; start with the PVD, even though it will fail
GetNextVD:
push eax
mov cx, 1
call ReadDisk
mov si, OFFSET SVDesc ; [ds:si] points to the desired first 6 bytes of this VD
xor di, di ; [es:di] points to the start of what we just read
mov cx, 6
repe cmpsb
je FoundSVD
mov al, es:0000h
cmp al, 0FFh ; is this the last Volume Descriptor?
je SVDError
pop eax
inc eax
jmp GetNextVD ; try another VD
FoundSVD: ; need to make sure this is a Joliet SVD - we need 025h, 02Fh, 045h in [88,89,90]
mov si, OFFSET JolietSig ; [ds:si] points to the Joliet Signature
mov di, 88 ; [es:di] points to the escape sequence field of the current SVD
mov cx, 3
repe cmpsb
je FoundJoliet
pop eax
inc eax
jmp GetNextVD
FoundJoliet:
;; Write 'D' to position 3.
mov ax, 04f44h
mov gs:[6], ax
mov eax, es:158 ; now get the rootstart and rootsize fields
mov [RootStart], eax
mov eax, es:166
mov [RootSize], eax
Step6: ; Load the Root Directory (SVD), and search it for SINGLDR
movzx ebx, [BlockSize]
div ebx ; eax has # blocks in root directory. Round up if necessary:
cmp edx, 0
je ReadyToLoad
add eax, 1
ReadyToLoad: ; we're going to assume that the root directory will not be bigger than 64K
mov ecx, eax
mov eax, [RootStart]
call ReadDisk
xor ebx, ebx ; bx will hold the start of the current entry
CheckEntry:
mov di, bx
add di, 25 ; let's check the file flags - should be 00
mov al, es:[di]
cmp al, 0
jne PrepNextEntry
; file flags are good. now check the file identifier:
mov si, OFFSET Stage2FileSize
xor cx, cx
mov cl, ds:[si] ; first byte is file name length
add cx, 2 ; add two because we check the length byte of the directory entry and the padding byte, too
add di, 7 ; now es:di points to the file length/name field, and ds:si has our desired content
repe cmpsb
je FoundEntry
PrepNextEntry:
xor cx, cx ; increment bx by adding the byte value in es:[bx]
mov cl, es:[bx] ; if es:[bx]==0 and ebx!= [RootSize], then we are in a padding zone
cmp cx, 0 ; designed to prevent a directory entry from spilling over a block.
jne LoadNext ; Should this be the case, we will increment bx until es:[bx] is not null
inc bx
jmp PrepNextEntry
LoadNext:
add bx, cx
cmp ebx, [RootSize]
jl CheckEntry
jmp FileNotFoundError
FoundEntry:
;; Write 'E' to position 5.
mov ax, 04f45h
mov gs:[8], ax
mov eax, es:[bx+2]
mov [FileStart], eax
mov eax, es:[bx+10]
mov [FileSize], eax
Step7: ; Load the file to 57c0:0000
mov cx, 057c0h
mov es, cx
movzx ebx, [BlockSize]
div ebx ; eax has # blocks in root directory
cmp edx, 0 ; on carry, there will be one more block
je ReadyToLoadFile
add eax, 1
ReadyToLoadFile:
mov ecx, eax
mov eax, [FileStart]
call ReadDisk
;; Write 'F' to position 6.
mov ax, 04f46h
mov gs:[10], ax
Step8: ; Now we need to set up the stack for SINGLDR and do a jump
xor cx, cx ; Always point the stack to 0000:7c00h - 12
mov ss, cx
mov sp, BootSecOrigin + StackOffset
movzx edx, [CDDrive]
push edx ; SINGLDR will need to know the boot drive #
pushd 04344h ; CD boot signature
pushw offset infloop ; return address = "infloop", which is the infinite loop
push cs
;; Write 'G' to position 7.
mov ax, 04f47h
mov gs:[12], ax
db 0EAh ; emit a long jump to 5000:7c00
dd 50007c00h
;;;;;;;;;;;;;;;;;;;;
; ReadDisk
;
; Inputs: eax = Block Number
; cx = number of blocks to read (warning: cx > 32 will cause overflow)
; es = destination segment
; Assumptions: 1 - assumes request will not cause overflow of es:00 (limit on # sectors)
; 2 - assumes int13 extensions available
ReadDisk PROC NEAR
pushad
mov dl, [CDDrive] ; set the drive
pushd 00
push eax ; push 64-bit block number (top half always null)
push es
pushw 00h ; push transfer address
push cx ; # sectors
pushw 0010h ; this request packet is 16 bytes
mov ah,42h ; extended read
mov si,sp ; ds:si = address of params
int 13h ; perform the read
add sp, 10h ; clean the stack and return
popad
ret
ReadDisk ENDP
;;;;;;;;;;;;;;;;;;;;
; Error Routines (these are jump points that never return)
SVDError:
mov si, offset SvdFailMsg
call PrintString
@@:
jmp @b
FileNotFoundError:
mov si, offset FileNotFoundMsg
call PrintString
@@:
jmp @b
PrintString:
psnext:
lodsb
or al, al
jz done
;;; Write directly to memory.
mov ah, 047h
mov bx, [Cursor]
mov gs:[bx], ax
add bx, 2
mov [Cursor], bx
mov bx, 07h ; normal attribute
mov ah, 0eh ; default print 1 char
int 10h
jmp psnext
done:
ret
infloop:
jmp infloop
;;;;;;;;;;;;;;;;;;;;
; Global Vars
RootStart DD 0
RootSize DD 0
CDDrive DB 0
BlockSize DW 0
FileStart DD 0
FileSize DD 0
Cursor DW 640
;;;;;;;;;;;;;;;;;;;;
; String Constants
SVDesc DB 02h, "CD001"
JolietSig DB 25h, 2fh, 45h ; this is the value of the escape sequence for a Joliet CD
; we'll use it as the signature...
Stage2FileSize DB OFFSET Stage2FilePad - OFFSET Stage2File
Stage2File DB 0,"S",0,"i",0,"n",0,"g",0,"l",0,"d",0,"r" ; in unicode, this is how our filename will appear
Stage2FilePad DB 0
SvdFailMsg DB 10,13,"SVD Failed",0
FileNotFoundMsg DB 10,13,"File not found",0
;;;;;;;;;;;;;;;;;;;;
; Boot Sector Signature
ORG 510
DW 0AA55h
end start
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Thanks a million! If anyone can make sense of how this works and point me in the right direction I will be forever indebted!
