//////////////////////////////////////////////////////////////////////// ; CHANGELOG ; [ ] - определение попытки сделать загрузочным не первый раздел //////////////////////////////////////////////////////////////////////// ; Программа записи на FDD/HDD boot-загрузчика и файлов системы. ; ; Загружает сист. файлы из корня диска, с которого была ; загружена система. ; Фитчи программы: ; В отличие от оригинального boot-инсталлятора, эта может ; переписывать уже установленный boot-загрузчик. ; Файлы системы (system.dos, system.exe) могут иметь ; любые размеры. ; При загрузке компьютера с дискеты, запрашивается новая ; дискета для создания из нее загрузочной. ; ; include 'shared_includes/constants/sp2000.inc' include 'shared_includes/constants/bios_equ.inc' include 'shared_includes/constants/dss_equ.inc' include 'shared_includes/macroses/accelerator.z80' include 'shared_includes/macroses/macros.z80' include 'shared_includes/structures/FileSystem.inc' DEFINE EXEinfoMACRO 1 MACRO _mEXEinfo BLOCK 10,' ' ; Выравнивание для красивого отображения в HEX BYTE ' Bootloader ' BYTE ' installer ' BYTE ' for DSS. ' BYTE ' Vasil Ivanov, ' BYTE ' Anatoliy ' BYTE ' Belyanskiy. ' BYTE ' Sprinter Team, ' BYTE ' 2023 ' ENDM ; версия программы major_version equ 1 ; ст. номер версии minor_version equ 5 ; мл. номер ;; org_addr EQU #8000 + CLP_Buffer code_addr EQU BEGIN program_start EQU BEGIN stack_point EQU #BFFE Loader_length EQU 0 ; page_buffer equ #C000 ; буфер файлов ;; include 'Shared_Includes/constants/EXE_Header.z80' ORG org_addr BEGIN: in a,(SLOT3) ld (port+1),a ; сохр. порт push ix call save_path ; сохр. тек. диск и путь ld c,Dss.Version ; узнать версию ДОС RST ToDSS ex de,hl ; hl=тек. версия ld de,#0146 ; 1.70.810 d=версия, e=модификация, bc - номер сборки. de = #0146, bc = 810 dos ver 1.70.810 and a sbc hl,de ;[ ] 17.12.2023 загрузка с активного раздела, а не с первого ;jr nc,version_ok jr z,.check_build ; если номер версии 1.70 jr nc,version_ok ; если номер версии больше 1.70 ; .old_ver: pop hl ld a,11 ; индекс строки "Error: Need DSS version 1.70..." call print_string ld a,-1 jp exit ;[ ] 17.12.2023 загрузка с активного раздела, а не с первого .check_build: ld hl,810 ; 1.70.810 d=версия, e=модификация, bc - номер сборки. de = #0146, bc = 810 dos ver 1.70.810 sbc hl,bc jr nc,BEGIN.old_ver ; version_ok: xor a ; индекс строки титла call print_string pop hl ; ком-строка ; выделить параметр ком-строки call get_drive_letter jp c,help ; нет параметров ld (disk),a ; заданный номер диска ; узнать номер boot-диска системы ld bc,Dss.BootDSK.Get RST ToDSS ld (boot_disk),a ; диск (A=0,B=1,..) ; проверить на совпадение дисков ld hl,disk cp (hl) jr nz,.next ld hl,confirm_flag ld (hl),1 ; уст. флаг ; ; Чтение в банки файлов системы ; .next: ld a,(boot_disk) ; диск загрузки ОС ld hl,root_path ; "X:\" корень диска add a,'A' ld (hl),a ld c,1Dh ; смена каталога RST ToDSS ;-------------------------------------------- ; Чтение файла system.exe ;-------------------------------------------- ld hl,name2 ; имя файла call read_file ; вся работа по загрузке файла в страницы jr nc,read_file1_ok ; освоб. блок памяти read_file_err: ld a,(id_blck) ; идентиф. блока памяти ld c,3Eh RST ToDSS ld a,-1 ; код ошибки jp exit ; сохр. раб. ячейки файла system.exe read_file1_ok: ld hl,file_handle ; откуда ld de,hFile1 ; куда ld bc,6 ldir ;-------------------------------------------- ; Чтение файла system.dos ;-------------------------------------------- ld hl,name1 ; имя файла call read_file ; вся работа по загрузке файла в страницы jr nc,read_file2_ok ; освоб. блок памяти system.exe file_err1: ld a,(id_mem) ; идентиф. блока памяти ld c,3Eh RST ToDSS jr read_file_err ; освоб. блок памяти system.dos read_file2_ok: confirm_flag+*: ld a,0 or a jr z,no_confirm ld a,(boot_disk) ; сист. диск cp 2 jr nc,no_confirm ; не дисководы ; запросить целевой диск ld a,(disk) ; заданный номер диска add a,'A' ld (messages.lett2),a ld a,5 ; индекс строки "Insert destination disk..." call print_string ld bc,3035h ; ждем нажатия клавиши RST ToDSS no_confirm: ld a,2 ; индекс строки "Installing boot loader..." call print_string ; Уст. целевой диск/путь ld a,(disk) ; целевой диск ld hl,root_path ; "X:\" строка пути add a,'A' ld (hl),a ld c,1Dh ; смена тек. каталога RST ToDSS ;-------------------------------------------- ; Записать boot-загрузчик call write_boot_loader jr c,write_error ; ошибка работы с девайсом ; ld a,3 ; индекс строки "Writing system files..." call print_string ; Запись файла system.dos ld hl,name1 ; имя файла call write_file jr nc,ok_write1 jr file_err1 ; ok_write1: ; освободить память ld a,(id_blck) ; блок system.dos ld c,3Eh RST ToDSS ; ; загр. раб. ячейки ld hl,hFile1 ; откуда ld de,file_handle ; куда ld bc,6 ldir ; Запись файла system.exe ld hl,name2 ; имя файла call write_file ; освободить память push af ld a,(id_blck) ; блок system.exe ld c,3Eh RST ToDSS pop af jr c,exit ; ошибка ; ld a,(disk) ; заданный номер диска add a,'A' ld (messages.lett1),a ld a,1 ; индекс строки "System installed on disk " call print_string ld a,(confirm_flag) or a jr z,exit ; запросить системный диск ld a,(boot_disk) ; сист. диск cp 2 jr nc,exit-1 ; не дисководы add a,'A' ld (messages.lett3),a ld a,6 ; индекс строки "Insert system disk..." call print_string ld bc,3035h ; ждем нажатия клавиши RST ToDSS xor a ; код "Ok" exit: push af call restore_path ; восст. тек. диск и путь port: ld a,-1 ; сохр. порт out (SLOT3),a pop af ld c,41h ; выход в ДОС ld b,a RST ToDSS jr $ help: ld a,8 ; индекс строки "Invalid drive specification" call print_string ld a,4 ; индекс строки хэлпа err_mes: call print_string ld a,1 ; код ошибки jr exit write_error: ld a,7 ; индекс строки "Can't install boot on this disk" jr err_mes root_path: db 'X:\',0 ; путь name1: db "SYSTEM.DOS",0 name2: db "SYSTEM.EXE",0 ;------------------------------------------------- ; Записать boot-загрузчик на FDD/HDD ; вход: нет ; выход: CF - ошибка работы с девайсом ;------------------------------------------------- write_boot_loader: ld a,(disk) ; заданный номер диска ld c,1 ; open device rst 18h ret c ld hl,close_device ; точка выхода push hl ld a,(disk) ; заданный номер диска ld hl,0 ; ст. разряд лог. сектора ld ix,0 ; мл. разряд ld de,buffer ; куда ld bc,0105h ; прочитать 1 сектор (boot) rst 18h ret c ; ошибка чтения ld a,(buffer+21) ; байт формата cp #F0 ; 1.44Mb ret c ; незнакомый формат jr z,write_to_floppy cp #F9 ; 720kB jr z,write_to_floppy cp #FA ; RAM disk jr z,write_to_ram_disk ; pop hl ; восст. баланс стека ; call close_device cp #F8 ; винт jp z,write_to_hard_disk scf ; незнакомый формат ret ; закрыть девайс close_device: push af ; сохр. флаг ld a,(disk) ; заданный номер диска ld c,2 ; close device rst 18h pop af ret ;------------------------------------------------- ; Запись boot-загрузчика на дискету ; ; вход: данные из buffer ; выход: CF - при ошибке записи ;------------------------------------------------- write_to_floppy: ld a,(buffer+16) ; число копий FAT-ов or a scf ret z ; ошибка dec a ; --число копий jr z,overwrite_floppy ; загрузчик уже записан, перезаписать его ; настроить ячейки boot-сектора ld (buffer+16),a ; число копий FAT-ов ld hl,(buffer+14) ; зарезерв. секторов ld bc,(buffer+22) ; секторов на FAT ld a,b or c scf ret z ; 0 секторов на FAT add hl,bc ld (buffer+14),hl ; зарезерв. секторов overwrite_floppy: ; записать boot-сектор назад ld a,(disk) ; заданный номер диска ld hl,0 ; ст. разряд лог. сектора ld ix,0 ; мл. разряд ld de,buffer ; откуда ld bc,0106h ; записать 1 сектор rst 18h ret c ; ошибка записи ; записать загрузчик ld a,(disk) ; заданный номер диска ld hl,0 ; ст. разряд лог. сектора ld ix,1 ; мл. разряд ld de,code_loader ; откуда (код загрузчика) ld bc,0306h ; записать 3 сектора (размер загр.) rst 18h ret ;------------------------------------------------- ; Запись boot-загрузчика на драйв ; ; вход: нет ; выход: CF-ошибка записи ;------------------------------------------------- write_to_ram_disk: write_to_: ld a,(disk) ; номер заданного диска ld de,#55AA ld bc,0 * 256 + 8 rst #18 ex af,af' ;[ ] 17.12.2023 загрузка с активного раздела, а не с первого ld b,a inc c scf ret z ; !TODO загрузка с расширенного раздела не поддерживается dec c push bc ; B - PHISICAL DRIVE NUMBER, C - PARTITION RECORD NUMBER IN DRIVE MBR ; [x] 02/02/2024 проверка на влезаемость загрузчика (чтоб не попортить фат) LD HL,0 LD IX,0 LD DE,buffer LD BC,1*256 + BIOS.DRV_READ RST ToBIOS POP BC LD HL,(buffer + _sBOOT_SECTOR_PARAMS.RESERVED_SECTORS) LD DE,04 ;!HARDCODE минимальное расстояние на драйве от нулевого сектора до фата (длина загрузчика + 1) AND A SBC HL,DE RET C ; push bc ld a,b ld hl,0 ; ст. разряд лог. сектора ld ix,1 ; мл. разряд ld de,code_loader ; откуда (код загрузчика) ld bc,3*256 + BIOS.DRV_WRITE ; записать 3 сектора (размер загр.) rst ToBIOS ;[ ] 17.12.2023 загрузка с активного раздела, а не с первого pop bc ; ret write_to_hard_disk: ;[ ] 17.12.2023 загрузка с активного раздела, а не с первого CALL write_to_ RET C ; PUSH BC ; B - PHISICAL DRIVE NUMBER, C - PARTITION RECORD NUMBER IN DRIVE MBR LD A,B LD HL,0 LD IX,0 LD DE,buffer LD BC,1*256 + BIOS.DRV_READ RST ToBIOS ; check signature LD HL,(buffer+510) ;!HARDCODE Signature word LD DE,#AA55 AND A SBC HL,DE POP BC ; B - PHISICAL DRIVE NUMBER, C - PARTITION RECORD NUMBER IN DRIVE MBR SCF RET NZ PUSH BC ; set active in buffer INC C LD HL,buffer + #01BE + #30 ;!HARDCODE MBR: Offset of last record of partition table in the MBR LD DE,#10 ; размер одной записи MBR LD B,4 ;!HARDCODE MBR: Number of entries in the partition table .loop: XOR A LD (HL),A ; LD A,C CP B JR NZ,.next ; LD A,#80 LD (HL),A ; .next: AND A SBC HL,DE DJNZ .loop ; save buffer to disk POP BC ; B - PHISICAL DRIVE NUMBER, C - PARTITION RECORD NUMBER IN DRIVE MBR ld a,b ld hl,0 ; ст. разряд лог. сектора ld ix,0 ; мл. разряд ld de,buffer ; откуда (код загрузчика) ld bc,1*256 + BIOS.DRV_WRITE ; записать 3 сектора (размер загр.) JP ToBIOS ; ;------------------------------------------------- ; Выделить заданный диск из ком-строки ; ; вход: hl=буфер строки ; выход: a=номер диска ; CF-при ошибке ;------------------------------------------------- get_drive_letter: inc hl ; буфер строки ld de,buffer ; буфер для выдел. параметра ld c,43h ; выделить параметр ком. строки RST ToDSS ld de,buffer ld a,(de) inc de ld c,a ; сохр. 'a' ld a,(de) inc de cp ':' jr nz,get_drive_err ; диск не задан ld a,(de) inc de or a jr nz,get_drive_err ; > 1 параметра ld a,c ; восст. 'a' cp 'A' jr c,get_drive_err cp 'z'+1 jr nc,get_drive_err res 5,a sub 'A' or a ret ; get_drive_err: scf ; ошибка ret ;---------------------------------------------------- ; сохр. тек. системный диск и путь ;---------------------------------------------------- save_path: ld c,2 ; узнать диск RST ToDSS ld (sys_disk),a ld hl,sys_path ld c,1Eh ; узнать путь RST ToDSS ret ;---------------------------------------------------- ; восст. тек. системный диск и путь ;---------------------------------------------------- restore_path: ld a,(sys_disk) ld c,1 ; смена диска RST ToDSS ld hl,sys_path ld c,1Dh ; смена пути RST ToDSS ret disk: db 0 ; номер заданного диска boot_disk: db 0 ; номер boot-диска системы ; раб. ячейки тек. файла ; ; чтение: system.exe, далее system.dos ; запись: system.dos, далее system.exe file_handle: db -1 ; дескриптор файла id_blck: db -1 ; идентиф. выдел. блока памяти ; lsize: dw 0 ; мл.разряд размера файла hsize: dw 0 ; ст.разряд ; сохр. данные system.exe hFile1: db -1 ; дескр. файла id_mem: db -1 ; идентиф. блока ; dw 0 ; мл.разряд dw 0 ; ст.разряд ; ; ; ; ; ; сообщения messages: db 0 db "\r\nBoot and System files Installer v" ;0 db major_version + '0','.' db (minor_version / 10) + '0',(minor_version % 10) + '0','.' db "\r\n\nCopyright (c) 2006-2022 Vasil Ivanov." db "\r\n\nCopyright (c) 2023 Sprinter Team." db "\r\n\n",0 ; db "System successfully installed on disk " ;1 .lett1: db "X:\r\n\n",0 ; db "Installing boot loader...\r\n\n",0 ;2 db "Writing system files...\r\n\n",0 ;3 ; db "Syntax: SYS X:\r\n" ;4 db " where X: - drive letter (A..Z)\r\n\n",0 ; db "Insert destination disk in drive " ;5 .lett2: db "X:\r\n" db "and strike any key when ready ...\r\n\n",0 ; db "Insert system disk in drive " ;6 .lett3: db "X:\r\n" db "and strike any key when ready ...\r\n\n",0 ; db "Can't install boot on this disk\r\n\n",0 ;7 db "Invalid drive specification\r\n\n",0 ;8 db " Error: Can't open file\r\n\n",0 ;9 db " Error: Can't allocate memory\r\n\n",0 ;10 db " Error: Need DOS version 1.70.811 or higher\r\n\n",0 ;11 db " Error: Reading error\r\n\n",0 ;12 db " Error: Can't create file\r\n\n",0 ;13 db " Error: Writing error\r\n\n",0 ;14 .endmess: db 0 ; Вывести строку по индексу ; вход: a=индекс строки print_string: call get_string ; поиск строки по ее индексу в 'a' ld c,5Ch ; вывод строки RST ToDSS ret ; поиск строки по ее индексу в 'a' get_string: ld hl,messages ; список мессаг для индекс. доступа ld bc,messages.endmess - messages ; размер списка inc a ex af,af' xor a ex af,af' get_loop: ex af,af' cpir ret po ret nz ex af,af' dec a jr nz,get_loop ret ;==================================================== ; Вся работа по загрузке файла в страницы ; вход: hl=имя файла ; выход: CF-при ошибке ;==================================================== read_file: ld a,1 ; на чтение ld c,11h ; открыть файл RST ToDSS jr nc,ok ; без ошибок ld a,9 ; индекс "Can't open file" call print_string scf ret ok: ld (file_handle),a ; дескр. файла ld hl,0 ld ix,0 ld bc,0215h ; указатель на конец файла RST ToDSS ld (hsize),hl ; ст.разряд размера файла ld (lsize),ix ; мл.разряд call get_memory ; расч. и выдел. страницы под файл jr c,not_enough ; не хватает памяти call file_to_bank ; загр. файл в страницы close_file: ld a,(file_handle) ; дескр. файла ld c,12h ; закрыть файл RST ToDSS ret ; not_enough: call close_file ld a,10 ; индекс "Can't allocate memory" call print_string scf ret ;---------------------------------------------------- ; По размеру файла рассчитать необходимое ; число страниц и выделить их. ; Выход: CF - при нехватке памяти ;---------------------------------------------------- get_memory: ld hl,(hsize) ; ст.разряд размера файла ld bc,(lsize) ; мл.разряд ld de,4000h ; делитель (размер страницы) xor a scf malloc1: rr d rr e jr c,malloc2 rr h rr l rr b rr c jr nc,malloc1 ld a,1 jr malloc1 ; malloc2: or a jr z,$+3 inc bc xor a cp b scf ret nz ; выделить блок памяти ld b,c ; b=число страниц ld c,3Dh RST ToDSS ld (id_blck),a ; идентиф. блока ret ;---------------------------------------------------- ; Загрузить файл в страницы ;---------------------------------------------------- file_to_bank: ld hl,0 ld ix,0 ld a,(file_handle) ; дескр. файла ld bc,0015h ; указатель на начало файла RST ToDSS ld a,(id_blck) ; идентиф. блока памяти ld b,0 ; лог. номер страницы в блоке ld c,0C4h ; получить физ. номер страницы в блоке rst 08h ret c loop_to_bank: push af out (SLOT3),a ld hl,page_buffer ; #C000 куда ld de,4000h ; сколько ld a,(file_handle) ; дескр. файла ld c,13h ; читать файл RST ToDSS pop bc jr nc,ok_to_bank ld a,12 ; индекс "Reading error" call print_string scf ret ; ok_to_bank: cp -1 ; прочитано меньшее число байт ? ret z ; да ld a,b ; a=физич. страница ld c,0C7h ; получить номер след. физ. страницы блока rst 08h ret c cp 255 jr nz,loop_to_bank ; не последняя страница ret ;==================================================== ; Запись файла на диск ; вход: hl=имя файла ; выход: CF-при ошибке ;==================================================== write_file: ld a,20h ; атрибут "архивный" ld c,0Ah ; создать файл RST ToDSS jr nc,create_ok ; без ошибок ld a,13 ; индекс "Can't create file" call print_string scf ret ; create_ok: ld (file_handle),a ; дескр. файла ld hl,close_file ; закр. файл push hl ; точка выхода ; ; чтение файла из банок и запись на диск ld a,(id_blck) ; идентиф. блока памяти ld b,0 ; лог. номер страницы в блоке ld c,0C4h ; получить физ. номер страницы в блоке rst 08h ret c write_loop: push af out (SLOT3),a ld hl,(lsize) ; мл.разряд размера файла ld de,(hsize) ; ст.разряд ld bc,4000h xor a sbc hl,bc ld b,a ex de,hl sbc hl,bc ex de,hl jr c,write_end ; записать остаток ld (lsize),hl ld (hsize),de ; ld hl,page_buffer ; #C000 откуда ld de,4000h ; сколько ld a,(file_handle) ; дескр. файла ld c,14h ; запись файла RST ToDSS pop bc jr nc,write_ok ld a,14 ; индекс "Writing error" call print_string scf ret ; write_ok: cp -1 ; записано меньшее число байт ? scf ret z ; да, на диске нет места ld a,b ; a=физич. страница ld c,0C7h ; получить номер след. физ. страницы блока rst 08h ret c cp 255 jr nz,write_loop ; не последняя страница ret ; write_end: pop af ; баланс стека ld de,(lsize) ; сколько ld a,e or d ret z ; 0 байтов ld hl,page_buffer ; #C000 откуда ld a,(file_handle) ; дескр. файла ld c,14h ; запись файла RST ToDSS ret ; ДОС-загрузчик code_loader: include 'dssboot.asm' ; универсальный загрузчик для старого и нового доса code_loader.size EQU $-code_loader DISPLAY " dssboot size: ", /D,code_loader.size, " bytes. Sectors: ",code_loader.size/512 ; 512 байт, буфер boot-сектора buffer equ $ sys_disk equ buffer+513 ; диск системы sys_path equ sys_disk+1 ; путь системы