MAB01057%UFRJ.BITNET@cornellc.cit.cornell.edu (Marcelo Amarante Ferreira Gomes) (06/16/90)
Hi. Since I had no time (nor patience :-) to handle the problems I was having with the transmition of this package, I decided to post the entire thing without any encoding. Though it may not get through ok :-( it is better than not having anything at all, so here it is: --------------------- cut here for readme.1st -------------------------- This package installs new code in the master boot record of your hard disk. This new code will ask you wich partition you want to boot from, thus allowing you to install multiple bootable OS's in the same hard disk. Unhappily I have little time to adapt the installation program to run under Minix, but I guess nobody will find much difficulty on that. It's harder to do the way I've done: in MS/DOS (with Turbo C). The package contains four files: - readme.1st (this file) - setboot.asm (the new code, in assembler) - instboot.c (the installator, in C) - makefile.mak (makefile build and install everything) If you find any difficulty installing this, please post your questions to the list, and not directly to me. Your doubts may be everyone else's. There is plenty of documentation in the sources, but I had little time to translate them to English, so that most of it is still in Portuguese, my native language. The important parts of it were translated, though. Enjoy. Marcelo A. Ferreira Gomes (Wally Gator) <MAB01057@UFRJ.bitnet> ------------------------- cut here for makefile.mak -------------------- SetBoot: SetBoot.bin instBoot SetBoot.bin SetBoot.bin: SetBoot.exe exe2bin $* SetBoot.exe: SetBoot.obj tlink $* SetBoot.obj: SetBoot.asm tasm $* ------------------------- cut here for setboot.asm -------------------- ;;======================================================;; ;; ;; ;; SetBoot.asm ;; ;; ;; ;; Boot sector for multiple operating systems ;; ;; in a single hard disk. ;; ;; ;; ;; Rewritten by Marcelo A. Ferreira Gomes ;; ;; original by Motti (Mordehai) Bazar ;; ;; ;; ;;======================================================;; ; ; ;-----------------------------------------------; ; Definicoes de constantes: ; ;-----------------------------------------------; ; ; Chamadas `a BIOS: ; Video Equ 10h ; Escrita no video Kbd Equ 16h ; Leitura de teclado DiskIO Equ 13h ; E/S em disco ; ; Caracteres especiais: ; CR Equ 0Dh ; Carriage return LF Equ 0Ah ; Line feed BkSpc Equ 08h ; Back space CtrlU Equ 15h ; Control-U (cancela linha) ; ; Enderecos e offsets: ; BootLoc Equ 7C00h ; Endereco do Boot Sector na memoria BootSig Equ 7DFEh ; Endereco da assinatura (AA55) MoveTo Equ 0600h ; Para onde relocar-se PartTbl Equ MoveTo + 01BEh ; Offset da tabela de particoes Passwd Equ BootMsg ; Senha: "BootX"; X = A, B, C ou D ; ; Setor de boot valido: ; Signatr Equ 0AA55h ; ; ;-----------------------------------------------; ; Inicio do codigo ; ;-----------------------------------------------; CODE Segment BYTE Public 'CODE' ; HBoot Proc NEAR ; Org 0h Assume CS:Code, DS:Code ; Start of code: relocate itself, so new OS's boot sector can be loaded BStart: Cli Xor Ax, Ax ; Ax = 0 Mov Ss, Ax ; Ss = 0 Mov Sp, BootLoc ; Ajusta a nova pilha Mov Si, Sp ; Si = Endereco fonte (p/ copiar) Mov Es, Ax Mov Ds, Ax Sti Cld Mov Di, MoveTo ; Di = Endereco de destino Mov Cx, 100h ; 256 words = 512 bytes a mover Rep MovSW ; Reloca o codigo para "MoveTo" Push Cx ; Agora Cx contem zero ! Mov Ax, MoveTo + OFFSET IniBoot Push Ax RetF ; "Retorna" para a proxima instrucao, IniBoot: ; ja' devidamente relocada. ; ; Marca todas as particoes como inativas: ; Mov Bx, PartTbl ; Faz Bx apontar para a tab. de part. Mov BYTE PTR [Bx], 0 ; Zero: particao inativa Mov BYTE PTR 16[Bx], 0 Mov BYTE PTR 32[Bx], 0 Mov BYTE PTR 48[Bx], 0 ; ; ; Mostra o prompt do boot: 'Boot da particao (A-D): ' ; WrPrmpt: Mov Si, MoveTo + OFFSET BootMsg Call ImpMsg ; ; ; Get user's response ; TryAgain: Mov Si, MoveTo + OFFSET Passwd Xor Dx, Dx ; Conta teclas erradas GetPass: Mov Ah, 0 ; Funcao: 0 = leitura ... Int Kbd ; do teclado Cmp Al, CtrlU ; Ctrl-U ? Je TryAgain ; Sim: anula a entrada Cmp Al, BkSpc ; E' back-space ? Jne NoBkSpc Cmp Si, MoveTo + OFFSET Passwd Je GetPass Dec Si Jmp GetPass NoBkSpc: Cmp Al, CR ; Fim da resposta ? Jz GotPass Mov Bl, Al Xor Al, [Si] ; Compara Al com [Si], ignorando And Al, NOT 20h ; distincao maiuscula/minuscula Jne GetRest Inc Si Jmp GetPass GetRest: Inc Dx ; Mais uma tecla errada GetAnother: Push Dx Push Bx Mov Ah, 0 ; Funcao: 0 = leitura ... Int Kbd ; do teclado Pop Bx Pop Dx Cmp Al, CtrlU ; Ctrl-U ? Je TryAgain ; Sim: anula a entrada Cmp Al, BkSpc ; E' back-space ? Jne CkCr Dec Dx ; Sim: menos uma tecla errada Jz GetPass ; Se erros=0, checa a senha de novo. Jmp GetAnother ; senao, pega outra tecla (errada) CkCr: Cmp Al, CR ; E' CR ? Jne GetRest ; Nao: continua lendo o teclado ; ; ; Find out from wich partition one wants to boot ; GotPass: Push Dx Push Si Push Bx Mov Si, MoveTo + OFFSET CrLf Call ImpMsg Pop Bx Pop Si Pop Dx Cmp Dx, 1 ; Se nao houve exatamente uma tecla Jnz WrPrmpt ; ... "errada", volta ao comeco Cmp BYTE PTR [Si], ' ' ; Verifica se a senha esta' ok Jne WrPrmpt ; Nao: pergunta de novo. Or Bl, 20h ; Ignora maiuscula/minuscula Cmp Bl, 'a' Jb WrPrmpt Cmp Bl, 'd' Ja WrPrmpt Mov Si, PartTbl ; Endereco base: tabela de particoes Sub Bl, 'a' ; Calcula o offset na tabela: Mov Cl, 4 ; ( caracter - 'a' ) * 16 Shl Bx, Cl Xor Bh, Bh ; Para isto, Bh tem de ser zero. Add Si, Bx ; ; ; Ativate the selected partition (writting it back) ; GotPart: Mov BYTE PTR [Si], 80h Push Si Mov Ax, 0301h ; Ah = escrever, Al = 1 setor Mov Bx, MoveTo ; Bx = este setor modificado Mov Cx, 1 ; Ch = trilha 0, Cl = setor 1 Mov Dx, 80h ; Dl = drive C:, Dh = cabeca 0 Int DiskIO ; ; Atencao: o registro "SI" ficou na pilha ! ; ; ; "Suja" a sua assinatura no Boot Sector, para nao haver confusao ; Mov Si, BootSig Mov WORD PTR [Si], NOT Signatr ; ; Restaura o "SI" da pilha ; Pop Si ; ; ; Tryes to read selected partition's boot sector ; Mov Dx, [Si] ; Dl = drive, Dh = cabeca Mov Cx, [Si+2] ; Ch = trilha, Cl = setor Mov Bp, Si ; Salva o ponteiro p/ particao Mov Di, 5 ; Contador de "retry's" RdBoot: Mov Bx, BootLoc ; Lugar do boot em memoria Mov Ax, 0201h ; Ah = ler, Al = 1 setor Push Di Int DiskIO Pop Di Jnc GoodRd ; Sai fora se leu direito ; Xor Ax, Ax ; Senao: recalibrar Int DiskIO Dec Di Jnz RdBoot ; ... e tentar de novo ; ; ; Read error on that partition: ; Display error message and start over ; Mov Si, MoveTo + OFFSET ErrLd ImpErr: Call ImpMsg Jmp IniBoot ; ; ; Boot Sector read: checks signature ; GoodRd: Mov Si, MoveTo + OFFSET NoOSys Mov Bx, BootSig Cmp WORD PTR [Bx], Signatr Jne ImpErr ; ; ; Finally, calls the boot sector just read ; Before that: ; Si = Boot partition's entry to partition table ; Bx = Number of starting cylinder of this partition ; Mov Si, Bp ; Restaura o ponteiro p/ a entrada Xor Ax, Ax ; Monta o endereco de "retorno" Push Ax Mov Ax, BootLoc Push Ax ; Mov Ax, WORD PTR 2[Si] ; Ah = cilindro, Al = setor Xor Bh, Bh Mov Bl, Al Shl Bx, 1 Shl Bx, 1 ; Bh = 2 bits mais significativos Mov Bl, Ah ; Bl = 8 bits menos significativos ; RetF ; Chama o setor de boot ; ;-----------------------------------------------; ; Routine to print a message on the screen. ; ; On entry, [Di] = string ; ;-----------------------------------------------; ImpMsg: LodSB Or Al, Al Jz ImpFim Mov Bx, 7 Mov Ah, 0Eh Int Video Jmp ImpMsg ImpFim: Ret ; ;-----------------------------------------------; ; Rotine to print a hex number ; ; On entry: Ax = number. ; ; On exit: Si is preserved. ; ;----------------------------- ; ; This routine was used to debug the program, ; ; and is no longer used. It may be omitted, if ; ; necessary to save space. ; ;-----------------------------------------------; PrHex: Push Si Mov Cl, 12 PrLoop: Push Ax Push Cx Shr Ax, Cl And Ax, 0Fh Or Al, 30h Cmp Al, 3Ah Jb OkHex Add Al, 7 OkHex: Mov Bx, 7 Mov Ah, 0Eh Int Video Pop Cx Pop Ax Sub Cl, 4 Jnc PrLoop Push Ax Mov Si, MoveTo + OFFSET CrLf Call ImpMsg Pop Ax Pop Si Ret ;----------------------------- ; BootMsg Db 'Boot from Partition (A-D): ', 0 ErrLd Db 'Error loading operating system.', CR, LF, 0 NoOSys Db 'No operating sistem in partition.' CrLf Db CR, LF, 0 ; HBoot EndP ; CODE EndS ; End --------------------------- cut here for instboot.c -------------------- /* * Instboot.c: * * THIS PROGRAM COPIES THE MASTER BOOT SECTOR OF A HARD DISK TO * A DISK FILE OR VICE-VERSA. IT SHOULD BE USED TO ALTER THE CODE IN * THE MASTER BOOT RECORD WITHOUT MODIFYING THE PARTITION TABLE. */ /* * Includes necessarios ( do Turbo C ) */ #include <bios.h> /* Funcoes do BIOS (como "biosdisk") */ #include <mem.h> /* Funcoes de manipulacao de memoria */ #include <stdio.h> /* Biblioteca padrao de E/S */ /* * Definicoes de constantes */ #define LEITURA 0x02 /* Funcao de leitura da BIOS */ #define ESCRITA 0x03 /* Funcao de escrita da BIOS */ #define WINCHST 0x80 /* Codigo do primeiro disco rigido */ #define N_BYTES 0x01BE /* Tamanho maximo do codigo de boot */ /* * Prototipos de funcoes: * * Se seu compilador nao suporta prototipos, simplesmente remova * as tres linhas abaixo. */ int instala ( char *arquivo ); int guarda ( char *arquivo ); int main ( int argc, char *argv | ); /* * Instala: * * Esta funcao copia o conteudo de um arquivo para o setor de boot * de um disco rigido, mantendo a tabela de particoes que havia la'. */ instala( arquivo ) char *arquivo; { FILE *fp; char newBoot BUFSIZ |; char oldBoot BUFSIZ |; if ( (fp = fopen( arquivo, "rb" )) == NULL ) { fprintf( stderr, "Erro na abertura de \"%s\".\n", arquivo ); return -1; } if ( fread( newBoot, 1, sizeof( newBoot ), fp ) > N_BYTES ) fprintf( stderr, "Aviso: \"%s\" sera truncado.\n", arquivo ); if ( biosdisk( LEITURA, WINCHST, 0, /* Lado 0 */ 0, /* trilha 0 */ 1, /* setor 1 */ 1, /* 1 unico setor */ oldBoot ) ) { fprintf( stderr, "Erro na leitura da tabela de particoes.\n" ); return -1; } /* * Mantem a tabela antiga de particoes ! */ memcpy( & newBoot N_BYTES |, & oldBoot N_BYTES |, 0x0200 - N_BYTES ); if ( biosdisk( ESCRITA, WINCHST, 0, 0, 1, 1, newBoot ) ) { fprintf( stderr, "Erro na escrita do novo boot.\n" ); return -1; } fclose( fp ); return 0; } /* * Guarda: * * Esta funcao copia o conteudo do setor de boot de um disco rigido * para um arquivo, excetuando-se a tabela de particoes. */ guarda( arquivo ) char *arquivo; { FILE *fp; char oldBoot BUFSIZ |; if ( biosdisk( LEITURA, WINCHST, 0, 0, 1, 1, oldBoot ) ) { fprintf( stderr, "Erro na leitura do setor de boot.\n" ); return -1; } if ( (fp = fopen( arquivo, "wb" )) == NULL ) { fprintf( stderr, "Erro na abertura de \"%s\".\n", arquivo ); return -1; } /* * Nao guarda a tabela de particoes, so' o codigo de boot ! */ if ( fwrite( oldBoot, 1, N_BYTES, fp ) != N_BYTES ) { fprintf( stderr, "Erro na escrita de \"%s\".\n", arquivo ); return -1; } fclose( fp ); return 0; } main ( argc, argv ) int argc; char *argv |; { char resp 80 |; if ( argc > 2 ) { fprintf( stderr, "Use: INSTBOOT\nou INSTBOOT arqBoot\n" ); return 1; } if ( argc == 2 ) { return instala( argv 1 | ); } else do { printf( "\n1 - Copiar o setor de boot para um arquivo\n" ); printf( "2 - Copiar um arquivo para o setor de boot\n" ); printf( "\nQual operacao desejada (1/2) ? " ); gets( resp ); switch( *resp ) { case '1': printf( "Para qual arquivo ? " ); gets( resp ); return guarda( resp ); case '2': printf( "Qual o arquivo a instalar ? " ); gets( resp ); return instala( resp ); default: fprintf( stderr, "Selecione a operacao 1 ou 2.\n" ); } } while( 1 ); }