; ************************************************************************** ; BOOT - This code contains: ; - TUOX boot record code ; - code to store boot record to disk(ette) ; ; Modified by Petr Smidak, member of 1999 Bootstrap group, after ; old Bootstrap group(s) ; ; ************************************************************************** Ideal model TINY P386 ; few 386 instruction, but not registers (so far) DataSeg ; 0:7C00h = address where BIOS loads boot record STACK_TOP = 7C00H SHIFT = 7C00H - 103H ; PSP = 100H bytes, JMP BOOT_BEGIN = 3 bytes FIRST_MODUL = 0700H ; Address where to load first module ; First module = Loader org 100h CodeSeg STARTUPCODE JMP BOOT_BEGIN ; TUOX boot record begins here ; Some is the same as MS-DOS (version 4.0 or higher) boot record ; Every value named in sectors is relative to boot sector ; Boot sector relative number is 0. Boot_Start: JMP SHORT @@Start ; Jump over data NOP ; Near jump expected, short one used ; so we need one extra byte here VersionID db 'TUOX2.0',0 ; Company and version BytesPerSec dw ? ; the most frequently 512B per sector db ? ; Unused StartImageSecs dw ? ; First available sector for image LoaderSize db ? ; Size of LOADER in sectors SizeImageSec dw ? ; Image size in sectors TotalSectors dw ? ; Total sector number on the disk FormatID db ? ; F0 = floppy, F8 = harddisk LoaderDataSec dw ? ; First sector of LOADER SectorsPerCyl dw ? ; Sectors per track (cylinder) Sides dw ? ; Number of sides (heads) on disk(ette) dw ? ; Unused dw ? ; Unused dd ? ; Unused DriveNo db ? ; 0 = 1st floppy, 80h = 1st harddisk db ? ; Unused db ? ; Unused VolumeSerialNo db 1,2,3,4 ; Volume serial number 0102-0304 VolumeLabel db 'TUOXsysdisk' ; Volume label (max. 11 chars) db 8 dup (?) ; 8 bytes ; Boot record end (total 62 bytes) ; Here come the variables that TUOX needs RAMDiskSize dw 0FFFFh ; Size of memory block reserved for RAM disk ; in paragraphs (1MB-16B) ; Boot main code @@Start: ; init segments except ES CLI mov ax, ds ; DS:SI = actual partition structure mov es, ax XOR AX, AX MOV SS, AX MOV SP, STACK_TOP ; Stack initiation MOV DS, AX STI ; When booting from harddisk, DS:SI pointers to actual ; partition structure. We need some parameters from there. ; Else we'll fill this structure with diskette parameters. cmp [BYTE DriveNo + SHIFT], 80h jnb savpar ; Fill partition structure buffer with diskette default parameters mov di, offset PartBuf + SHIFT inc di mov [BYTE ds:di], 0 ; BeginHead = 0 inc di mov [WORD ds:di], 1 ; BeginSecCyl = 1 add di, 14 jmp near saveend ; Else save real partition structure to our buffer savpar: mov cx, 10h ; 16 bytes of structure mov di, offset PartBuf+SHIFT savparloop: mov al, [BYTE es:si] ; let it save mov [BYTE ds:di], al inc di inc si loop savparloop ; Common parameters saveend: ; save added informations mov al, [BYTE DriveNo + SHIFT] ; Drive mov [BYTE ds:di], al add di, 1 mov ax, [WORD RAMDiskSize + SHIFT] ; RAMDisk size mov [WORD ds:di], ax xor ax, ax ; init ES mov es, ax ; Look if LOADER in disk detectloader: MOV AL, [LoaderSize + SHIFT] OR AL, AL JZ @@Boot_Failure ; Loader there, so init drive & load it XOR AX, AX MOV DL, [BYTE DriveNo + SHIFT] INT 13H ; Device reset (AH = 0) JC @@Boot_Failure ; Reset error MOV SI, OFFSET StartMsg1 + SHIFT CALL WriteString ; Print message MOV SI, OFFSET VersionID + SHIFT CALL WriteString ; Print message MOV SI, OFFSET StartMsg2 + SHIFT CALL WriteString ; Print message MOV CX,3 ; Try to read 3 times MOV BX, FIRST_MODUL shr 4 MOV ES, BX XOR BX, BX ; First modul begins at 0070:0000 ; Now we'll read the loader from reserved sector @@Read_Continue: MOV AX, [LoaderDataSec + SHIFT] CALL calc_sec ; relative sector -> physical CHS @@three: PUSH CX MOV AX, 0201h ; Read a sector INT 13H POP CX JNC @@Continue LOOP @@three JMP SHORT @@Boot_Failure @@Continue: INC [LoaderDataSec + SHIFT] ; Next sector to read ADD BX, [BytesPerSec + SHIFT] ; BX = new address to read to DEC [LoaderSize + SHIFT] JNZ @@Read_Continue MOV SI, OFFSET OKMsg + SHIFT CALL WriteString ; Print message ; Set ES:DI to pointer to Partiton buffer. Loader use it mov di, offset PartBuf + SHIFT mov ax, cs mov es, ax ; Now go to Loader JMP FAR (FIRST_MODUL-100h) shr 4 : 0100h ; 100h = loader PSP ; Boot failed (read error, loader not found), message & try again @@Boot_Failure: MOV SI, OFFSET BootFailMsg + SHIFT CALL WriteString ; Print error message XOR AH, AH ; BIOS keyboard service INT 16H ; Wait for key stroke INT 19H ; Try to load boot sector again proc WriteString near ; Print an ASCIIZ string at DS:SI @@Write_Begin: LODSB ; Next character OR AL, AL JZ @@Write_End ; AL=0 => end of ASCIIZ string MOV AH, 0EH ; BIOS service - write character MOV BL, 0FFH ; Char's attribute INT 10H JMP SHORT @@Write_Begin @@Write_End: RET endp WriteString proc calc_sec near ; Calculates side, cylinder & abs. sector number from relative sector number ; Input: AX = relative sector ; Relative sector = Cyl# * SPC * Heads + Head# * SPC + Sec# - 1 (zero base) ; Results: prepare register to int 13/[02 or 03] (without AX) ; Modified registers: AX, DX, CX ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ; We suppose the maximum relative sector equals to 0FFFFh. ; For bootstrap it should be enough. ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! XOR DX, DX DIV [WORD SectorsPerCyl + SHIFT] PUSH DX XOR DX, DX DIV [WORD Sides + SHIFT] MOV DH, DL ; HEAD ; PartBuf + 1 = BeginHead add dh, [BYTE PartBuf + 1 + SHIFT] ; DH = absolute head ; PartBuf + 2 = BeginSecCyl mov cx, [WORD PartBuf + 2 + SHIFT] and cx, 0FFC0h rol cl, 2 xchg cl, ch add ax, cx ; AX = absolute cylinder pop cx ; CX = calculated sector push ax mov ax, [WORD PartBuf + 2 + SHIFT] and ax, 3Fh add cx, ax ; CX = absolute sector pop ax ;Head overflow cmp dh, [BYTE Sides + SHIFT] jb @@testsec mov dh, 0 add ax, 1 ; Sector overflow @@testsec: cmp cx, [SectorsPerCyl + SHIFT] jna @@dontaddhead mov cx, 1 add dh, 1 ; Head overflow again @@dontaddhead: cmp dh, [BYTE Sides + SHIFT] jna @@dontaddcyl mov dh, 0 add ax, 1 @@dontaddcyl: xchg ah, al ror al, 2 or al, cl mov cx, ax MOV DL, [DriveNo + SHIFT] ; DRIVE NUMBER RET endp calc_sec PartBuf db 19 dup(?) ; 16 bytes of partition structure ; + 1 byte for DRIVE identification ; + 2 bytes for RAMdisk size BootFailMsg db 'Non-System disk or disk error', 13, 10 KeyPressMsg db 'Press any key to reboot...', 13, 10, 0 StartMsg1 db 13,10,'Starting ',0 StartMsg2 db ' Operating System ... ', 0 OKMsg db 'OK', 13, 10, 0 @@BootCode_End: BOOT_BEGIN: ; get command line to buffer 'cmd' mov si, 80h movzx cx, [BYTE ds:si] ; CX = velikost inc cx mov di, offset cmd cld rep movsb ; transmission 'cmd' to big letters cld mov ax, offset cmd mov si, ax mov di, ax mov cx, 80h cik: lodsb cmp al, 'a' jb neeee cmp al, 'z' ja neeee sub al, 'a'-'A' neeee: stosb loop cik ; go to main writing code jmp main PROC str2num ; Transmission of hexadecimal string to real number ; input : AX = string offset (one or two characters) ; output : BX = wanted number ; CF = 1, if transmission gone wrong mov bx, 0 cld clc mov si, ax mov di, ax mov ax, 0 mov cx, 2 ; max 2 characters cak: lodsb cmp al,'0' ; AL must be '0'-'9' or 'A'-'F' jb tr_err cmp al,'9' jb number cmp al,'A' jb tr_err cmp al,'F' ja tr_err ; transmission of characters 'A'-'F' to number sub al,55 ; 'A'=65 => 65-55=10, (10 decimal is A hexadec.) shl bx,4 add bx,ax loop cak jmp finish ; transmission of characters '0'-'9' to number number: sub al,48 ; '0'=48 => 48-48=0 shl bx,4 add bx,ax loop cak jmp finish ; wrong input tr_err: stc finish: ret ENDP str2num main: ; cmd+2 = 1st character of command line mov al, [BYTE cmd + 2] mov si, offset HelpMsg cmp al, 0 ; when no parameters je ParDrvErr cmp al, '?' ; or given '?', then jne ParDrvOk ; print help ParDrvErr: call WriteString jmp main_end ParDrvOk: mov ax, offset cmd + 2 ; first parameter = drive call str2num mov [BYTE DRIVE], bl cmp bl, 7Fh ja @@ReadMBR ; Don't read MBR when writing mov [BYTE HEAD], 0 ; to floppy mov [WORD CYLSEC], 1 jmp @@ReadBoot @@ReadMBR: ; cmd+5 = 4th character of command line mov al, [BYTE cmd + 5] mov si, offset HelpMsg cmp al, 0 ; if partition parameter not je @@Do_Write ; specified cmp al, '1' ; or not in range 1 to 4 jb @@Do_Write ; print help cmp al, '4' ja @@Do_Write mov bx, offset MBRbuffer mov dl, [BYTE DRIVE] mov dh, 0 ; MBR Head mov cx, 3 @@TryReadMBR: push cx mov cx, 1 ; MBR Cylinder & Sector mov ax, 0201H ; read MBR to buffer int 13h pop cx jnc @@ReadMBROK loop @@TryReadMBR mov si, offset DiskReadErrMBR jmp @@Do_Write @@ReadMBROK: mov ax, offset cmd + 5 call str2num ; get parameters of given partition mov ax, bx mov bx, 16 mul bx sub ax, bx add ax, 1beh mov di, ax add di, 1 mov cl, [BYTE MBRbuffer + di] mov [BYTE HEAD], cl ; BeginHead add di, 1 mov cx, [WORD MBRbuffer + di] mov [WORD CYLSEC], cx ; BeginCylSec ; Read original boot record before update @@ReadBoot: MOV BX, OFFSET BootBuffer MOV DL, [BYTE DRIVE] MOV DH, [BYTE HEAD] ; BeginHead = boot sector Head MOV CX, 3 @@TryRead: PUSH CX MOV CX, [WORD CYLSEC] ; boot sector Cylinder & Sector MOV AX, 0201H ; read boot to buffer INT 13H POP CX JNC @@ReadOK LOOP @@TryRead MOV SI, OFFSET DiskReadErr JMP @@Do_Write @@ReadOK: MOV SI, OFFSET Boot_Start MOV DI, OFFSET BootBuffer MOV CX, 11 REP MOVSB ; write my boot to buffer, but ADD SI, 27 ; skip disk parameters 12-38 byte ADD DI, 27 MOV CX, 472/2 REP MOVSW MOV AX, 0AA55H ; End of boot sector signature STOSW MOV CX, 3 @@TryWrite: PUSH CX MOV DL, [BYTE DRIVE] MOV DH, [BYTE HEAD] MOV CX, [WORD CYLSEC] MOV AX, 0301H MOV BX, OFFSET BootBuffer INT 13H ; Write buffer to boot sector POP CX JNC @@Write_OK LOOP @@TryWrite MOV SI, OFFSET WriteErrorMsg JMP SHORT @@Do_Write @@Write_OK: MOV SI, OFFSET WriteOKMsg @@Do_Write: CALL WriteString main_end: EXITCODE HelpMsg db 'Boot Record Writer by Petr Smidak & friends ' db 'from TUOX Bootstrap group, 1999', 13,10,13,10 db 'Boot - Real Boot record Code. IT LOADS TUOX.', 13,10,13,10 db 'BOOT.COM [? | ]', 13,10,13,10 db 'Parameters :',13,10 db ' ? - this help message', 13,10 db ' DRIVE = hexadecimal number', 13,10 db ' (0 = first floppy drive, ' db '1 = second floppy drive, ...', 13,10 db ' 80 = first harddisk, ' db '81 = second harddisk, ...)', 13,10 db ' PARTITION = partition number on choosed drive (1-4)', 13,10 db ' This has no effect, if drive < 80 (hexa)', 13,10,0 WriteErrorMsg db 'Boot Writing Error.', 13,10,0 DiskReadErr db 'Boot Reading Error.', 13,10,0 WriteOKMsg db 'Boot Record Was Successfully Written.', 13,10 db 'Load System Files Now.', 13,10,0 DiskReadErrMBR db 'MBR Reading Error.', 13,10,0 DRIVE db ? PARTBEG dw ? HEAD db ? CYLSEC dw ? hex db '0123456789ABCDEF' ; hexa znaky cmd db 8 dup(0), 78h dup(?) ; argumenty z PSP BootBuffer db 512 dup(?) MBRbuffer db 512 dup(?) ends end