📄 manager.asm
字号:
.MODEL LARGE
ASSUME CS:ADV_MAN_TEXT, DS:BOOT_DATA, ES:BOOT_DATA, SS:BOOT_DATA
PUBLIC _ADV_IPL, _ADV_MANAGER, _encrypt_password
LOCALS
SECT_SIZE EQU 512
MAX_MENU_ROWS EQU 16
MAX_PART_ROWS EQU 32
ADV_CODE_SIZE EQU 8192
ADV_DATA_SIZE EQU 2048
ADV_CODE_SECT EQU (ADV_CODE_SIZE/SECT_SIZE)
ADV_DATA_SECT EQU (ADV_DATA_SIZE/SECT_SIZE)
ADV_CODE_ADDR EQU (800h)
ADV_DATA_ADDR EQU (800h+ADV_CODE_SIZE)
ADV_MAGIC_VALUE EQU 0ABCDh
ADV_OPT_VIR_CHECK EQU 1
ADV_OPT_CLEAR_SCR EQU 2
ADV_OPT_DEF_MENU EQU 4
ADV_OPT_IGN_UNUSED EQU 8
OS_HIDDEN EQU 0FF80h
OS_ADV EQU 0FF81h
OS_UNKN EQU 0FFFFh
M_BOOT_EMPTY EQU 0
M_BOOT_PART EQU 1
M_BOOT_NEXT_HD EQU 2
M_BOOT_FLOPPY EQU 3
SHOW_ONE EQU 0
SHOW_LAST EQU 1
SHOW_NEXT EQU 2
SHOW_PREV EQU 3
SHOW_LAST3 EQU 4
M_OPT_PASSW EQU 1
INCLUDE COLORS.INC
X EQU 30
Y EQU 2
W EQU 50
; H EQU 16
KEYS_X EQU (X+4)
; KEYS_Y EQU (Y+H-2)
KEYS_W EQU (31+12)
DOT_X EQU (KEYS_X+11)
DOT_Y EQU (KEYS_Y)
DOT_NUM EQU (31)
DOT1 EQU 07h
DOT2 EQU 0FAh
TITLE_COLOR EQU Yellow+BakBlack
MENU_COLOR EQU BrWhite+BakBlack
ACTIVE_COLOR EQU Black+BakCyan
KEYS_KEY_COLOR EQU Yellow+BakBlack
KEYS_TXT_COLOR EQU BrCyan+BakBlack
BORDER_COLOR EQU BrGreen+BakBlack ; Yellow+BakBlue
DOTBAR_COLOR EQU BrWhite+BakBlack
BOOT_DATA SEGMENT AT 0h
ORG 600h
MBR_SECT DB 512 Dup(?)
ORG 7B0h
ADV_REL_SECT DD ?
ADV_RESERVED DD ?
adv_act_menu DB ?
adv_boptions DB ?
adv_abmmagic DB 4 Dup(?)
mbr_part_rec STRUC ; 16 bytes
b_boot_flag DB ?
b_chs_start DB 3 Dup(?)
b_os_id DB ?
b_chs_end DB 3 Dup(?)
b_rel_sect DD ?
b_num_sect DD ?
ENDS
part_rec mbr_part_rec 4 DUP(?)
ORG ADV_DATA_ADDR
ADV_SIGNATURE DB 15 Dup(?) ; "AdvBootManager",0
ADV_VERSION DB ?
adv_def_menu DB ?
adv_timeout DB ?
adv_options DB ?
adv_options2 DB ?
adv_password DW ?
adv_reserved2 DB 26 Dup(?)
adv_title DB 32 Dup(?)
adv_menu_rec STRUC ; 80 bytes
m_type DB ?
m_options DB ?
m_name DB 30 Dup(?)
m_tag DB ?
m_show DB ?
m_reserved DB 14 Dup(?)
m_num_keys DW ?
m_keys DW 15 Dup(?)
ENDS
adv_part_rec STRUC ; 16 bytes
p_os_id DW ?
p_tag DB ?
p_orig_row DB ?
p_reserved DB 4 Dup(?)
p_rel_sect DD ?
p_num_sect DD ?
ENDS
menu adv_menu_rec MAX_MENU_ROWS Dup(?)
part adv_part_rec MAX_PART_ROWS Dup(?)
ORG ADV_DATA_ADDR + ADV_DATA_SIZE
NUM_DISKS DB ?
DISK DB ?
DISK_NUM_CYLS DW ?
DISK_NUM_HEADS DW ?
DISK_NUM_SECTS EQU SECT_PER_TRACK
SECT_PER_CYL DW ?
SECT_PER_TRACK DW ?
_ScreenArea DD ? ; B800h:0000h
_ScreenWidth DB ? ; 80
_ScreenHeight DB ? ; 25
_ScreenLength DW ? ; 80*25
NUM_MENUS DW ?
ACT_MENU DW ?
MENU_PTR DW MAX_MENU_ROWS Dup(?)
PART_PTR DW MAX_MENU_ROWS Dup(?)
ACT_MBR_REC DW ?
ACT_PART_PTR DW ?
PART_TMP adv_part_rec 4 Dup(?)
PART_TMP2 adv_part_rec ?
MBR_SECT_BAK DB 512 Dup(?)
TMP DB 80 Dup(?)
SAV_BUFFER DB 4096 Dup(?)
SAV_BUFFER_ERR DB 640 Dup(?)
CURSOR_SAVE_XY DW ?
TICKS_PER_DOT DW ?
H DB ?
KEYS_Y DB ?
PASS_VALIDATED DW ?
FILL_KB_BUFFER DW ?
ALT_ENTER DW ?
LAST_PART DW ?
IMPORTED_FLAG DW ?
FD_PARAMS DB 4 Dup(?)
STACK_AREA DB 1024 Dup(?) ; Reserving at list 1k for stack
ORG 7C00h
OS_BOOT_SECT DB SECT_SIZE Dup(?)
BOOT_DATA ENDS
;----------------------------------------------------------------------
PUSH_REGS MACRO
push ax
push bx
push cx
push dx
push di
push si
push ds
push es
ENDM
;----------------------------------------------------------------
POP_REGS MACRO
pop es
pop ds
pop si
pop di
pop dx
pop cx
pop bx
pop ax
ENDM
;----------------------------------------------------------------
ADV_MAN_TEXT SEGMENT PARA PRIVATE 'CODE'
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 7C00h
xor cx, cx
mov dl, 80h
mov Word Ptr ADV_REL_SECT, 7
mov Word Ptr ADV_REL_SECT+2, 0
jmp debug_entry
ORG 600h
_ADV_IPL PROC NEAR
;
; BIOS loads MBR at 0000:7C00h
;
; Lets move code to 0000:0600h
;
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax ; CPU clears interrupt flag for next command
mov sp, 7C00h
cld
mov si, sp
mov di, 0600h
mov cx, 0100h
rep
movsw
; jmp 0000:@@ENTRY
DB 0EAh
DW (@@ENTRY-_ADV_IPL+600h), 0000
;
;
ErrBootMan EQU (@@M1-_ADV_IPL+600h)
BootAorHD EQU (@@M2-_ADV_IPL+600h)
ErrBootSct EQU (@@M3-_ADV_IPL+600h)
MsgNL EQU (@@M4-_ADV_IPL+600h)
;
@@M1: DB "Cannot load Boot Manager.",0Dh,0Ah
@@M2: DB "Boot from A or hard disk? ",0
@@M3: DB "Error reading Boot Sector."
@@M4: DB 0Dh,0Ah,0
;
ADV_CODE_CHECK_SUM DW 0
;
debug_entry:
@@ENTRY:
;GET_DISK_INFO PROC NEAR
;
; dl - disk number
;
cmp dl, 80h
jae @@skip
mov dl, 80h
@@skip:
mov DISK, dl
mov cl, 3
@@get_again:
mov ah, 08 ; Get disk parameters
int 13h
jnc @@eval
mov ah, 0
int 13h
loop @@get_again
jmp @@err1 ; Error
@@eval:
; mov NUM_DISKS, dl
xor ah, ah
mov al, dh
inc ax ; AX - Number of HEADS (SIDES)
mov DISK_NUM_HEADS, ax
xor bh, bh
mov bl, cl
and bl, 3Fh ; BX - Number of SECTORS / TRACK
mul bx
mov SECT_PER_CYL, ax
mov SECT_PER_TRACK, bx
mov bl, ch
shl cx, 1
shl cx, 1
and ch, 3
mov bh, ch
inc bx
mov DISK_NUM_CYLS, bx
;GET_DISK_INFO ENDP
;
; Read Advanced Boot Manager Data and Code
;
mov ax, Word Ptr ADV_REL_SECT
mov dx, Word Ptr ADV_REL_SECT+2
mov bx, ADV_DATA_ADDR
mov cx, ADV_DATA_SECT
call READ_N_SECT
jc @@err1
add ax, ADV_DATA_SECT
adc dx, 0
mov bx, ADV_CODE_ADDR
mov cx, ADV_CODE_SECT
call READ_N_SECT
jc @@err1
cmp [bx], ADV_MAGIC_VALUE
jne @@err1
;
jmp adv_code_entry_point
; jmp 0000h:0800h ; Jump to Boot Manager
; DB 0EAh
; DW 0800h,0000h
;
bad_boot_man:
@@err1:
mov si, ErrBootMan
@@err2:
call PRINT
mov ah, 0
int 16h ; Get a key
mov si, MsgNL
call PRINT
cmp al, 'A'
je @@floppy ; Boot from floppy
cmp al, 'a'
je @@floppy
;
; Find active partition on hard disk
;
@@part_tab:
mov cx, 4
mov di, 7BEh ; Address of the first record
@@next_part:
cmp Byte Ptr [di], 00
jnz @@read_hd ; Active partition found
add di, 10h
loop @@next_part
@@floppy: ; No active partition found
xor dx, dx
;mov dx, 0000 ; Lets boot from floppy
mov cx, 0001
jmp @@read_sect
@@read_hd:
mov dx, [di]
mov cx, [di+2]
@@read_sect:
mov bx, 7C00h
call READ_SECT
jnc @@go_boot
;
mov si, ErrBootSct
call PRINT
mov si, BootAorHD
jmp @@err2
;
@@go_boot:
mov dl, [di] ; Boot sector expects Drive# in DL
; jmp 0000h:7C00h ; Transfer control to loaded BootSector
DB 0EAh
DW 7C00h,0000h
;
;
;
REL_SECT_TO_CHS PROC NEAR
;
; Input: DX:AX - relative sector
; Output: DH,CX - CHS and DL - disk
; Destroys: AX
;
div SECT_PER_CYL ; AX=CYL, DX=SECT on CYL
mov cx, ax
shr cx, 1
shr cx, 1
and cl, 0C0h
mov ch, al
mov ax, dx
xor dx, dx
div SECT_PER_TRACK ; AX=HEAD, DX=SECT
mov dh, al
inc dl
and dl, 3Fh
or cl, dl
mov dl, DISK
ret
REL_SECT_TO_CHS ENDP
;
;
READ_N_SECT PROC NEAR
;
;
; ES:BX - Destination address
; DX:AX - Relative sector on disk
; CX - Number of sectors to read
;
; Returns: Flag CF set if error
;
push ax
push bx
push cx
push dx
@@next_sect:
push ax
push cx
push dx
call REL_SECT_TO_CHS
call READ_SECT
pop dx
pop cx
pop ax
jc @@end
add ax, 1
adc dx, 0
add bx, SECT_SIZE
loop @@next_sect
@@end:
pop dx
pop cx
pop bx
pop ax
ret
READ_N_SECT ENDP
;
;
;
READ_SECT PROC NEAR
;
; ES:BX - Address
; CX,DX - CHS
;
; Returns: CF set if error
;
push si
mov si, 3 ; We will try at most three times
@@try_again:
mov ax, 0201h ; Read (AH=02) 1 Sector (AL=01)
int 13h
jnc @@end
; We get here if there was an error
mov ah, 0 ; We will try to reset device
int 13h
dec si
jnz @@try_again
;
; We have tried three times, so we will give up
;
stc
@@end:
pop si
ret
READ_SECT ENDP
;
;
PRINT PROC NEAR
;
; ds:si - address of null terminated string to print
;
push ax
push bx
push si
mov ah, 0Eh
mov bh, 00h
@@pr1:
lodsb
or al, al
jz @@pr2
int 10h
jmp @@pr1
@@pr2:
pop si
pop bx
pop ax
ret
PRINT ENDP
;
;
GAP1 PROC
GAPLEN1 EQU (01B0h-(GAP1-_ADV_IPL))
IF GAPLEN1
DB GAPLEN1 DUP(0)
ENDIF
GAP1 ENDP
ADV_MBR_MISC DB 14+64+2 Dup(0)
_ADV_IPL ENDP
;
;
;
;
_ADV_MANAGER PROC NEAR
;
; IPL loads MANAGER at 0000h:0800h = 0800h
;
; SS:SP = 0000h:7C00h = 7C00h
;
ADV_MAGIC_NUM DW ADV_MAGIC_VALUE
;
adv_code_entry_point:
;
; First of all lets check integrity of code
;
CHECK_CODE_INTEGRITY PROC NEAR
xor bx, bx
mov cx, ADV_CODE_SIZE
shr cx, 1
mov si, ADV_CODE_ADDR
@@add_next_word:
lodsw
add bx, ax
loop @@add_next_word
cmp ADV_CODE_CHECK_SUM, 0
je @@initialize_sum
cmp ADV_CODE_CHECK_SUM, bx
je @@check_data_header
jmp bad_boot_man
@@initialize_sum:
mov ADV_CODE_CHECK_SUM, bx
@@check_data_header:
mov cx, 15
lea si, ADV_SIGNATURE
lea di, ADV_SIGNATURE2
repe
cmpsb
je @@data_header_valid
jmp bad_boot_man
@@data_header_valid:
CHECK_CODE_INTEGRITY ENDP
;
CHECK_INTERRUPT_VECTORS PROC
test adv_options, ADV_OPT_VIR_CHECK
jz @@ints_okay
mov cx, 1Dh ; Check interrupts 0h to 1Ch
mov bx, 3
@@next_int:
cmp byte ptr [bx], 0C0h ; They must be >= C000:0000h
jb @@int_changed
add bx, 4
loop @@next_int
mov bx, 4Ah*4-1 ; int 4Ah - User Alarm
cmp byte ptr [bx], 0C0h
jb @@int_changed
mov bx, 70h*4-1 ; int 70h - Real-Time Clock
cmp byte ptr [bx], 0C0h
jb @@int_changed
jmp @@ints_okay
@@int_changed:
lea si, VirusWarning
call PRINT
@@wait_enter:
mov ah, 0
int 16h ; Get a key
cmp al, 0Dh
jne @@wait_enter ; And loop until ENTER is pressed
lea si, VirusNL
call PRINT
@@ints_okay:
CHECK_INTERRUPT_VECTORS ENDP
;
;
jmp @@start
;
; Messages
;
ADV_SIGNATURE2 DB "AdvBootManager",0
Border DB "赏缓 喝图"
Border1 DB "谀砍 忱馁"
Mesg_OK DB " OK ",0
BottomKeysESC DB "ESC",0
BottomKeysText DB "ESC - Boot",0
BottomKeysEnt DB "Enter",0
BottomKeysText2 DB "Press Enter to boot from selected partition",0
MesgSetTimeout DB "Select menu timeout (+/-): ",0
MesgErrorRead DB "Error reading boot sector",0
MesgErrorSave DB "Error saving MBR to disk",0
MesgErrorSaveAdv DB "Error saving Advanced MBR to disk",0
MesgEnterPassword DB "Enter password:",0
MesgPasswordInvalid DB "Password invalid",0
MesgBootInvalid DB "Boot sector is invalid",0
MesgImported DB "One or more partitions was changed in MBR. Please, run PART.EXE",0
VirusWarning DB 0Dh, 0Ah
DB "One or more interrupts does not point to BIOS.", 0Dh, 0Ah
DB "This may be a sign of a stealth boot virus.", 0Dh, 0Ah
DB "Turn the computer OFF then ON and run antivirus.", 0Dh, 0Ah
DB "Or press ENTER to continue booting... ", 0
VirusNL DB 0Dh, 0Ah, 0
;
;
@@start:
call _conio_init
call CHECK_LAST_CYL
call IMPORT_NEW_PART
call PREP_MENU_LIST
call BACKUP_MBR_SECT
@@menu:
mov ax, NUM_MENUS
add ax, 6
mov H, al
add al, Y
sub al, 2
mov KEYS_Y, al
mov PASS_VALIDATED, 0
call INIT_SCREEN
call MAIN_MENU
call DONE_SCREEN
cmp ALT_ENTER, 1
jne @@no_need_to_wait
mov cx, 24 ; If user presses ALT-ENTER we will wait
@@L3: ; for about 1.5 seconds before proceding.
push cx
mov ah, 0
int 1Ah ; Read System Timer
mov bx, dx
@@WT1: int 1Ah ; Wait one timer tick
cmp bx, dx
je @@WT1
pop cx
loop @@L3
@@no_need_to_wait:
mov di, ACT_MBR_REC
mov dl, [di] ; Boot sector expects Drive# in DL
; jmp 0000h:7C00h ; Transfer control to loaded BootSector
DB 0EAh
DW 7C00h,0000h
_ADV_MANAGER ENDP
;
;
;
INIT_SCREEN PROC NEAR
test adv_options, ADV_OPT_CLEAR_SCR
jz @@skip1
mov ah, White+BakBlack
mov bl, 1
mov bh, 1
mov dl, 80
mov dh, 25
call _clear_window
mov bl, 1
mov bh, 1
call _move_cursor
@@skip1:
call _save_cursor
call _hide_cursor
mov bl, X
mov bh, Y
mov dl, W
mov dh, H
lea si, SAV_BUFFER
call _save_window
mov ah, BORDER_COLOR
lea si, Border
call _border_window
mov ah, TITLE_COLOR
add bx, 0109h
lea si, adv_title
call _write_string
mov ah, KEYS_TXT_COLOR
mov bl, KEYS_X
mov bh, KEYS_Y
lea si, BottomKeysText2
call _write_string
mov ah, KEYS_KEY_COLOR
add bl, 6
lea si, BottomKeysEnt
call _write_string
ret
INIT_SCREEN ENDP
;
;
;
DONE_SCREEN PROC NEAR
mov bl, X
mov bh, Y
mov dl, W
mov dh, H
lea si, SAV_BUFFER
call _load_window
call _restore_cursor
ret
DONE_SCREEN ENDP
;
;
;
PREP_MENU_LIST PROC NEAR
test adv_options, ADV_OPT_DEF_MENU
jz @@no_def_menu
mov al, adv_def_menu
mov adv_act_menu, al
@@no_def_menu:
mov ACT_MENU, 0
mov NUM_MENUS, 0
mov cx, 0
lea si, menu
mov di, 0
@@next:
cmp [si].m_type, M_BOOT_EMPTY
je @@cont
mov MENU_PTR[di], si
mov al, [si].m_tag
call PART_NUM_BY_TAG
jnc @@part_ok
cmp [si].m_type, M_BOOT_PART
je @@cont
mov ax, 0
@@part_ok:
mov PART_PTR[di], ax
cmp cl, adv_act_menu
jne @@skip
mov ax, NUM_MENUS
mov ACT_MENU, ax
@@skip:
add di, 2
inc NUM_MENUS
@@cont:
add si, SIZE adv_menu_rec
inc cx
cmp cx, MAX_MENU_ROWS
jne @@next
ret
PREP_MENU_LIST ENDP
;
;
;
PART_NUM_BY_TAG PROC NEAR
;
; Input: AL - Tag
; Output: AX - Pointer to partition
;
; CF - Set if part not found, AX=0
;
push bx
push cx
cmp al, 0
je @@fail
xor cx, cx
lea bx, part
@@next:
cmp [bx].p_tag, al
jne @@cont
clc
mov ax, bx
jmp @@end
@@cont:
add bx, SIZE adv_part_rec
inc cx
cmp cx, MAX_PART_ROWS
jne @@next
@@fail:
stc
mov ax, 0
@@end:
pop cx
pop bx
ret
PART_NUM_BY_TAG ENDP
;
;
;
MAIN_MENU PROC NEAR
;
; Main loop
;
cmp IMPORTED_FLAG, 10h
jb @@no_import
lea si, MesgImported
call SHOW_ERROR
@@no_import:
mov di, 0
mov FILL_KB_BUFFER, 1
@@while1:
mov ax, 0
jmp @@cond1
@@next1:
call SPRINTF_MENU
push ax
mov bl, (X+3)
mov bh, (Y+3)
add bh, al
cmp ax, ACT_MENU
mov ah, MENU_COLOR
jne @@norm1
mov ah, ACTIVE_COLOR
@@norm1:
lea si, TMP
call _write_string
pop ax
inc ax
@@cond1:
cmp ax, NUM_MENUS
jne @@next1
mov ALT_ENTER, 0
cmp di, 0
jne @@wait_key
; First time here
cmp adv_timeout, 0
je @@wait_key
xor ah, ah
mov al, adv_timeout
inc ax
shr ax, 1
mov TICKS_PER_DOT, ax
call DOT_BAR
jnc @@no_keys ; no keys was pressed - time run out
mov ah, 10h
int 16h
cmp al, ' '
jne @@cmp_keys
jmp @@wait_key
@@no_keys:
jmp @@boot
@@wait_key:
mov ah, 10h
int 16h
@@cmp_keys:
cmp ax, 48E0h
je @@up
cmp ax, 4800h
je @@up
cmp ax, 50E0h
je @@down
cmp ax, 5000h
je @@down
cmp ax, 47E0h
je @@home
cmp ax, 4700h
je @@home
cmp ax, 4FE0h
je @@end
cmp ax, 4F00h
je @@end
cmp ax, 3920h ; Space
je @@space
cmp ax, 1C0Dh ; Enter
je @@boot2short
cmp ax, 0E00Dh ; Enter
je @@boot2short
cmp ax, 1C00h ; Alt-Enter
je @@alt_boot2short
cmp ax, 0A600h ; Alt-Enter
je @@alt_boot2short
cmp ax, 011Bh ; ESC
je @@boot_esc2short
cmp al, 'A'
je @@boot_a_short
cmp al, 'a'
je @@boot_a_short
cmp al, 9 ; Tab
je @@boot_d_short
cmp al, 'H'
je @@hide_all
cmp al, 'h'
je @@hide_all
sub al, '1'
xor ah, ah
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -