linux-c-programming.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Boot code in C
@ 2004-07-05 13:49 kaushal
  2004-07-05 17:36 ` John T. Williams
  2004-07-06  5:26 ` Progga
  0 siblings, 2 replies; 4+ messages in thread
From: kaushal @ 2004-07-05 13:49 UTC (permalink / raw)
  To: linux-c-programming


Hello  all,
          I want to know if there is a way to  generate a binary file,
from  a C program(Not from an assembly code)(can use any Linux
tools)that can be burned on to a floppy and which ,say--  just prints a
string on to the screen.
I tried out to the following:


1.[kaushal@linuxbox]#cc Hello.c -static -o Hello
  [kaushal@linuxbox]#strip Hello
  [kaushal@linuxbox]#objcopy -O binary Hello Hello.bin
  [kaushal@linuxbox]#dd if=Hello.bin of=/dev/floppy


2.[kaushal@linuxbox]#cc Hello.c -S 
  [kaushal@linuxbox]#as Hello.s -o Hello
  [kaushal@linuxbox]#strip Hello
  [kaushal@linuxbox]#objcopy -O binary Hello Hello.bin
  [kaushal@linuxbox]#dd if=Hello.bin of=/dev/floppy

In the second case (2.)(Even if I don't give a "-static" switch for the
first one(1.)) the Hello size is MUCH less than its counterpart of case
(1.)
Either way it did not work.I think the problem occurs because of absence
of OS at boot time.So is there any way of atleast generating the
required assembly code from the C code(The optimised one).



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Boot code in C
  2004-07-05 13:49 Boot code in C kaushal
@ 2004-07-05 17:36 ` John T. Williams
  2004-07-06  5:26 ` Progga
  1 sibling, 0 replies; 4+ messages in thread
From: John T. Williams @ 2004-07-05 17:36 UTC (permalink / raw)
  To: kaushal; +Cc: linux-c-programming

there are a couple of issues involved.
1.  when you compile C programs they are linked against the at least the
C library on your computer.  You can take care of that by using the
-static directive with either the linker or the gcc, but you have to
have already installed the static version all libraries you link
against. which you can find out using the ldd tool
2.  System calls are part of The OS, so if you want a program to execute
w/o first loading the kernel, you can't make any system calls.  This
includes every input output function that I know of.  
3.  you need a boot loader.  The BIOS will load the bootsector of a
floppy into memory, and if your program is small enough to fit in the
boot sector, then you have no problem, otherwise you have to write code
to open your disk's filesystem, find your program, load it into memory
and then start executing it.  

In short, if you really want a program which runs off a floppy, and does
anything useful, you need to learn a little assembly.

	



On Mon, 2004-07-05 at 09:49, kaushal wrote:
> Hello  all,
>           I want to know if there is a way to  generate a binary file,
> from  a C program(Not from an assembly code)(can use any Linux
> tools)that can be burned on to a floppy and which ,say--  just prints a
> string on to the screen.
> I tried out to the following:
> 
> 
> 1.[kaushal@linuxbox]#cc Hello.c -static -o Hello
>   [kaushal@linuxbox]#strip Hello
>   [kaushal@linuxbox]#objcopy -O binary Hello Hello.bin
>   [kaushal@linuxbox]#dd if=Hello.bin of=/dev/floppy
> 
> 
> 2.[kaushal@linuxbox]#cc Hello.c -S 
>   [kaushal@linuxbox]#as Hello.s -o Hello
>   [kaushal@linuxbox]#strip Hello
>   [kaushal@linuxbox]#objcopy -O binary Hello Hello.bin
>   [kaushal@linuxbox]#dd if=Hello.bin of=/dev/floppy
> 
> In the second case (2.)(Even if I don't give a "-static" switch for the
> first one(1.)) the Hello size is MUCH less than its counterpart of case
> (1.)
> Either way it did not work.I think the problem occurs because of absence
> of OS at boot time.So is there any way of atleast generating the
> required assembly code from the C code(The optimised one).
> 
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Boot code in C
  2004-07-05 13:49 Boot code in C kaushal
  2004-07-05 17:36 ` John T. Williams
@ 2004-07-06  5:26 ` Progga
  2004-12-11  7:15   ` itmncm
  1 sibling, 1 reply; 4+ messages in thread
From: Progga @ 2004-07-06  5:26 UTC (permalink / raw)
  To: kaushal; +Cc: linux-c-programming

[-- Attachment #1: Type: text/plain, Size: 772 bytes --]

On Mon, Jul 05, 2004 at 07:19:29PM +0530, kaushal wrote:

>           I want to know if there is a way to  generate a binary file,
> from  a C program(Not from an assembly code)(can use any Linux
> tools)that can be burned on to a floppy and which ,say--  just prints a
> string on to the screen.
> I tried out to the following:

 If you are willing to use grub for booting your code, then -

	$ info multiboot

		-> Example -> Example OS code


 If you want a custome bootloader but grub to boot the executive, see the
attachment.  It's a mixture of C and (Nasm) Assembly.  The reference was
tiny.txt.



 Khoda Hafez
 Progga

* Attached is the bootloader BOOT12.* by Jhon Fine.  It's for fat12.
** Also Google for this file - "CompilingBinaryFilesUsingACompiler.pdf". 


[-- Attachment #2: c-kern.tar.bz2 --]
[-- Type: application/octet-stream, Size: 1415 bytes --]

[-- Attachment #3: BOOT12.bin --]
[-- Type: application/octet-stream, Size: 512 bytes --]

[-- Attachment #4: BOOT12.ASM --]
[-- Type: text/plain, Size: 12307 bytes --]

; boot12.asm  FAT12 bootstrap for real mode image or loader
; Version 1.0, Jul 5, 1999
; Sample code
; by John S. Fine  johnfine@erols.com
; I do not place any restrictions on your use of this source code
; I do not provide any warranty of the correctness of this source code
;_____________________________________________________________________________
;
; Documentation:
;
; I)    BASIC features
; II)   Compiling and installing
; III)  Detailed features and limits
; IV)   Customization
;_____________________________________________________________________________
;
; I)    BASIC features
;
;    This boot sector will load and start a real mode image from a file in the
; root directory of a FAT12 formatted floppy or partition.
;
;    Inputs:
; DL = drive number
;
;    Outputs:
; The boot record is left in memory at 7C00 and the drive number is patched
; into the boot record at 7C24.
; SS = DS = 0
; BP = 7C00
;_____________________________________________________________________________
;
; II)   Compiling and installing
;
;  To compile, use NASM
;
;  nasm boot12.asm -o boot12.bin
;
;  Then you must copy the first three bytes of BOOT12.BIN to the first three
;  bytes of the volume and copy bytes 0x3E through 0x1FF of BOOT12.BIN to
;  bytes 0x3E through 0x1FF of the volume.  Bytes 0x3 through 0x3D of the
;  volume should be set by a FAT12 format program and should not be modified
;  when copying boot12.bin to the volume.
;
;  If you use my PARTCOPY program to install BOOT12.BIN on A:, the
;  commands are:
;
;  partcopy boot12.bin 0 3 -f0
;  partcopy boot12.bin 3e 1c2 -f0 3e
;
;  PARTCOPY can also install to a partition on a hard drive.  Please read
;  partcopy documentation and use it carefully.  Careless use could overwrite
;  important parts of your hard drive.
;
;  You can find PARTCOPY and links to NASM on my web page at
;  http://www.erols.com/johnfine/
;_____________________________________________________________________________
;
; III)  Detailed features and limits
;
;   Most of the limits are stable characteristics of the volume.  If you are
; using boot12 in a personal project, you should check the limits before
; installing boot12.  If you are using boot12 in a project for general
; distribution, you should include an installation program which checks the
; limits automatically.
;
; CPU:  Supports any 8088+ CPU.
;
; Volume format:  Supports only FAT12.
;
; Sector size:  Supports only 512 bytes per sector.
;
; Drive/Partition:  Supports whole drive or any partition of any drive number
; supported by INT 13h.
;
; Diskette parameter table:  This code does not patch the diskette parameter
; table.  If you boot this code from a diskette that has more sectors per
; track than the default initialized by the BIOS then the failure to patch
; that table may be a problem.  Because this code splits at track boundaries
; a diskette with fewer sectors per track should not be a problem.
;
; File position:  The file name may be anywhere in the root directory and the
; file may be any collection of clusters on the volume.  There are no
; contiguity requirements.  (But see track limit).
;
; Track boundaries:  Transfers are split on track boundaries.  Many BIOS's
; require that the caller split floppy transfers on track boundaries.
;
; 64Kb boundaries:  Transfers are split on 64Kb boundaries.  Many BIOS's
; require that the caller split floppy transfers on track boundaries.
;
; Cluster boundaries:  Transfers are merged across cluster boundaries whenever
; possible.  On some systems, this significantly reduces load time.
;
; Cluster 2 limit:  Cluster 2 must start before sector 65536 of the volume.
; This is very likely because only the reserved sectors (usually 1) and
; the FAT's (two of up to 12 sectors each) and the root directory (usually
; either 15 or 32 sectors) precede cluster 2.
;
; Track limit:  The entire image file must reside before track 32768 of the
; entire volume.  This is true on most media up to 1GB in size.  If it is a
; problem it is easy to fix (see boot16.asm).  I didn't expect many people
; to put FAT12 partitions beyond the first GB of a large hard drive.
;
; Memory boundaries:  The FAT, Root directory, and Image must all be loaded
; starting at addresses that are multiples of 512 bytes (32 paragraphs).
;
; Memory use:  The FAT and Root directory must each fit entirely in the
; first 64Kb of RAM.  They may overlap.
;
; Root directory size:  As released, it supports up to 928 entries in the
; root directory.  If ROOT_SEG were changed to 0x7E0 it would support up
; to 1040.  Most FAT12 volumes have either 240 or 512 root directory
; entries.
;_____________________________________________________________________________
;
; IV)   Customization
;
;   The memory usage can be customized by changing the _SEG variables (see
; directly below).
;
;   The file name to be loaded and the message displayed in case of error
; may be customized (see end of this file).
;
;   The ouput values may be customized.  For example, many loaders expect the
; bootsector to leave the drive number in DL.  You could add "mov dl,[drive]"
; at the label "eof:".
;
;   Some limits (like maximum track) may be removed.  See boot16.asm for
; comparison.
;
;   Change whatever else you like.  The above are just likely possibilities.
;_____________________________________________________________________________


; Change the _SEG values to customize memory use during the boot.
; When planning memory use, remember:
;
; *)  Each of ROOT_SEG, FAT_SEG, and IMAGE_SEG must be divisible by 0x20
;
; *)  None of ROOT, FAT or IMAGE should overlap the boot code itself, or
;     its stack.  That means: avoid paragraphs 0x7B0 to 0x7DF.
;
; *)  The FAT area must not overlap the IMAGE area.  Either may overlap
;     the ROOT area;  But, if they do then the root will not remain in
;     memory for possible reuse by the next stage.
;
; *)  The FAT area and the root area must each fit within the first 64Kb
;     excluding BIOS area (paragraphs 0x60 to 0xFFF).
;
; *)  A FAT12 FAT can be up to 6Kb (0x180 paragraphs).
;
; *)  A FAT12 root directory is typically either 0x1E0 or 0x400 paragraphs
;     long, but larger sizes are possible.
;
; *)  The code will be two bytes shorter when FAT_SEG is 0x800 than when it
;     is another value.  (If you reach the point of caring about two bytes).
;
%define ROOT_SEG	0x60
%define FAT_SEG		0x800
%define IMAGE_SEG	0x900

%if ROOT_SEG & 31
  %error "ROOT_SEG must be divisible by 0x20"
%endif
%if ROOT_SEG > 0xC00
  %error "Root directory must fit within first 64Kb"
%endif
%if FAT_SEG & 31
  %error "FAT_SEG must be divisible by 0x20"
%endif
%if FAT_SEG > 0xE80
  %error "FAT must fit within first 64Kb"
%endif
%if IMAGE_SEG & 31
  %error "IMAGE_SEG must be divisible by 0x20"
%endif

; The following %define directives declare the parts of the FAT12 "DOS BOOT
; RECORD" that are used by this code, based on BP being set to 7C00.
;
%define	sc_p_clu	bp+0Dh		;byte  Sectors per cluster
%define	sc_b4_fat	bp+0Eh		;word  Sectors (in partition) before FAT
%define	fats		bp+10h		;byte  Number of FATs
%define dir_ent		bp+11h		;word  Number of root directory entries
%define	sc_p_fat	bp+16h		;word  Sectors per FAT
%define sc_p_trk	bp+18h		;word  Sectors per track
%define heads		bp+1Ah		;word  Number of heads
%define sc_b4_prt	bp+1Ch		;dword Sectors before partition
%define drive		bp+24h		;byte  Drive number

	org	0x7C00

entry:
	jmp	short begin
	nop

; Skip over the data portion of the "DOS BOOT RECORD".  The install method
; must merge the code from this ASM with the data put in the boot record
; by the FAT12 formatter.
;
	times 0x3B db 0

begin:
	xor	ax, ax
	mov	ds, ax
	mov	ss, ax
	mov	sp, 0x7C00
	mov	bp, sp
	mov	[drive], dl	;Drive number

	mov	al, [fats]	;Number of FATs
	mul	word [sc_p_fat]	; * Sectors per FAT
	add	ax, [sc_b4_fat]	; + Sectors before FAT
				;AX = Sector of Root directory

	mov	si, [dir_ent]	;Max root directory entries
	mov	cl, 4
	dec	si
	shr	si, cl
	inc	si		;SI = Length of root in sectors

	mov	di, ROOT_SEG/32	;Buffer (paragraph / 32)
	call	read_16		;Read root directory
	push	ax		;Sector of cluster two
%define sc_clu2 bp-2		;Later access to the word just pushed is via bp

	mov	dx, [dir_ent]	;Number of directory entries
	push	ds
	pop	es
	mov	di, ROOT_SEG*16

search:
	dec	dx		;Any more directory entries?
	js	error		;No
	mov	si, filename	;Name we are searching for
	mov	cx, 11		;11 characters long
	lea	ax, [di+0x20]	;Precompute next entry address
	push	ax
	repe cmpsb		;Compare
	pop	di
	jnz	search		;Repeat until match

	push word [di-6]	;Starting cluster number

	mov	ax, [sc_b4_fat]	;Sector number of FAT
	mov	si, [sc_p_fat]	;Length of FAT
	mov	di, FAT_SEG/32	;Buffer (paragraph / 32)
	call	read_16		;Read FAT

next:
	pop	bx		;Cluster number
	mov	si, bx		;First cluster in this sequence
	mov	ax, bx		;Last cluster in this sequence

.0:
	cmp	bx, 0xFF8	;End of file?
	jae	.2		; Yes
	inc	ax		;Last cluster plus one in sequence

	;Look in FAT for next cluster
	mov	di, bx		;Cluster number
	rcr	bx, 1		;1.5 byte entry per cluster
				;bx = 0x8000 + cluster/2
				;c-bit set for odd clusters

	mov	bx, [bx+di+FAT_SEG*16-0x8000]
	jnc	.1
	shr	bx, 1
	shr	bx, 1
	shr	bx, 1
	shr	bx, 1
.1:	and	bh, 0xF

	cmp	ax, bx		;Is the next one contiguous?
	je	.0		;Yes: look further ahead
.2:	sub	ax, si		;How many contiguous in this sequence?
	jz	eof		;None, must be done.

	push	bx		;Save next (eof or discontiguous) cluster
	
	mov	bl, [sc_p_clu]	;Sectors per cluster
	mov	bh, 0		;  as a word
	mul	bx		;Length of sequence in sectors
.3:	mov	di, IMAGE_SEG/32 ;Destination (paragraph / 32)
	add	[.3+1], ax	 ;Precompute next destination
	xchg	ax, si		;AX = starting cluster ;SI = length in sectors
	dec	ax
	dec	ax		;Starting cluster minus two
	mul	bx		; * sectors per cluster
	add	ax, [sc_clu2]	; + sector number of cluster two
	adc	dl, dh		;Allow 24-bit result

	call	read_32		;Read it
	jmp	short next	;Look for more

eof:
	jmp	IMAGE_SEG:0

error:	mov	si, errmsg	;Same message for all detected errors
	mov	ax, 0xE0D	;Start message with CR
	mov	bx, 7
.1:	int	10h
	lodsb
	test	al, al
	jnz	.1
	xor	ah, ah
	int	16h		;Wait for a key
	int	19h		;Try to reboot

read_16:
	xor	dx, dx

read_32:
;
; Input:
;    dx:ax = sector within partition
;    si    = sector count
;    di    = destination segment / 32
;
; The sector number is converted from a partition-relative to a whole-disk
; (LBN) value, and then converted to CHS form, and then the sectors are read
; into (di*32):0.
;
; Output:
;    dx:ax  updated (sector count added)
;    di     updated (sector count added)
;    si = 0
;    bp, ds preserved
;    bx, cx, es modified

.1:	push	dx			;(high) relative sector
	push	ax			;(low) relative sector

	add	ax, [sc_b4_prt]		;Convert to LBN
	adc	dx, [sc_b4_prt+2]

	mov	bx, [sc_p_trk]		;Sectors per track
	div	bx			;AX = track ;DX = sector-1
	sub	bx, dx			;Sectors remaining, this track
	cmp	bx, si			;More than we want?
	jbe	.2			;No
	mov	bx, si			;Yes: Transfer just what we want
.2:	inc	dx			;Sector number
	mov	cx, dx			;CL = sector ;CH = 0
	cwd				;(This supports up to 32767 tracks
	div	word [heads]		;Track number / Number of heads
	mov	dh, dl			;DH = head

	xchg	ch, al			;CH = (low) cylinder  ;AL=0
	ror	ah, 1			;rotate (high) cylinder
	ror	ah, 1
	add	cl, ah			;CL = combine: sector, (high) cylinder

	sub	ax, di
	and	ax, byte 0x7F		;AX = sectors to next 64Kb boundary
	jz	.3			;On a 64Kb boundary already
	cmp	ax, bx			;More than we want?
	jbe	.4			;No
.3:	xchg	ax, bx			;Yes: Transfer just what we want
.4:	push	ax			;Save length
	mov	bx, di			;Compute destination seg
	push	cx
	mov	cl, 5
	shl	bx, cl
	pop	cx
	mov	es, bx
	xor	bx, bx			;ES:BX = address
	mov	dl, [drive]		;DL = Drive number
	mov	ah, 2			;AH = Read command
	int	13h			;Do it
	jc	error
	pop	bx			;Length
	pop	ax			;(low) relative sector
	pop	dx			;(high) relative sector
	add	ax, bx			;Update relative sector
	adc	dl, dh
	add	di, bx			;Update destination
	sub	si, bx			;Update count
	jnz	.1			;Read some more
	ret

errmsg	db	10,"Error Executing FAT12 bootsector",13
	db	10,"Press any key to reboot",13,10,0

size	equ	$ - entry
%if size+11+2 > 512
  %error "code is too large for boot sector"
%endif
	times	(512 - size - 11 - 2) db 0

filename db	"LOADER  BIN"		;11 byte name
	db	0x55, 0xAA		;2  byte boot signature

[-- Attachment #5: tiny.txt --]
[-- Type: text/plain, Size: 3048 bytes --]

The smallest pmode + C program I could write is shown below,
in three files. I compiled with GCC, not GPP, and got no
warnings.

This code doesn't check for a 32-bit CPU or V86 mode. If you
try to run it inside a DOS box, Windows will kill it.

load.asm is assembled to aout format instead of COFF, because
DJGPP COFF doesn't let you mix 16- and 32-bit code.

;/****************************************************************************
;       file load.asm
;****************************************************************************/
[SECTION .text]
[BITS 16]
[GLOBAL start]
start:  xor ebx,ebx             ; now in real mode (16-bit)
	mov bx,cs
	shl ebx,4
	mov eax,ebx		; EAX=EBX=CS<<4
	lea eax,[ebx]
	mov [gdt2 + 2],ax	; set descriptor base address=EAX
	mov [gdt3 + 2],ax
	shr eax,16
	mov [gdt2 + 4],al
	mov [gdt3 + 4],al
	mov [gdt2 + 7],ah
	mov [gdt3 + 7],ah
	lea eax,[ebx + gdt]	; point gdt_ptr to the gdt
	mov [gdt_ptr + 2],eax	; EAX=linear address of gdt
	push dword 0		; zero EFLAGS (interrupts off,
	popfd			;  IOPL=0, NT bit=0)
	lgdt [gdt_ptr]
	mov eax,cr0
	or al,1
	mov cr0,eax
	jmp SYS_CODE_SEL:do_pm
[BITS 32]
do_pm:  mov ax,SYS_DATA_SEL     ; now in 32-bit pmode
	mov ds,eax		; EAX works, one byte smaller :)
	mov ss,eax
        nop
	mov es,eax
	mov fs,eax
	mov gs,eax
	xor eax,eax		; zero top 16 bits of ESP
	mov ax,sp
	mov esp,eax
[EXTERN _main]
	call _main		; call C code
	jmp $			; freeze

[SECTION .data]
; null descriptor
gdt:	dw 0			; limit 15:0
	dw 0			; base 15:0
	db 0			; base 23:16
	db 0			; type
	db 0			; limit 19:16, flags
	db 0			; base 31:24
; linear data segment descriptor
LINEAR_SEL	equ	$-gdt
        dw 0xFFFF               ; limit 0xFFFFF (1 meg? 4 gig?)
	dw 0			; base for this one is always 0
	db 0
	db 0x92			; present,ring 0,data,expand-up,writable
        db 0xCF                 ; page-granular (4 gig limit), 32-bit
	db 0
; code segment descriptor
SYS_CODE_SEL	equ	$-gdt
gdt2:	dw 0xFFFF
	dw 0			; (base gets set above)
	db 0
	db 0x9A			; present,ring 0,code,non-conforming,readable
	db 0xCF
	db 0
; data segment descriptor
SYS_DATA_SEL	equ	$-gdt
gdt3:	dw 0xFFFF
	dw 0			; (base gets set above)
	db 0
	db 0x92			; present,ring 0,data,expand-up,writable
	db 0xCF
	db 0
gdt_end:

gdt_ptr:
	dw gdt_end - gdt - 1	; GDT limit
	dd gdt			; linear, physical address of GDT

;/****************************************************************************
;       file hello.c
;****************************************************************************/
#include <string.h> /* movedata() */

#define	LINEAR_SEL	0x08
#define	SYS_DATA_SEL	0x18

int main(void)
{
	const char Msg[] = "h e l l o ";

	movedata(SYS_DATA_SEL, (unsigned)Msg,
		LINEAR_SEL, 0xB8000,
		sizeof(Msg));
	return 0;
}

;/****************************************************************************
;	file build.bat
;*****************************************************************************/
nasm -f aout -o load.o load.asm
gcc -c -O2 -Wall -g -o hello.o hello.c
ld -o pm.com -oformat binary -Ttext=0x100 load.o hello.o /djgpp/lib/libc.a


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Boot code in C
  2004-07-06  5:26 ` Progga
@ 2004-12-11  7:15   ` itmncm
  0 siblings, 0 replies; 4+ messages in thread
From: itmncm @ 2004-12-11  7:15 UTC (permalink / raw)
  To: linux-c-programming

Progga wrote:
> On Mon, Jul 05, 2004 at 07:19:29PM +0530, kaushal wrote:
> 
> 
>>          I want to know if there is a way to  generate a binary file,
>>from  a C program(Not from an assembly code)(can use any Linux
>>tools)that can be burned on to a floppy and which ,say--  just prints a
>>string on to the screen.
>>I tried out to the following:
> 
> 
>  If you are willing to use grub for booting your code, then -
> 
> 	$ info multiboot
> 
> 		-> Example -> Example OS code
> 
> 
>  If you want a custome bootloader but grub to boot the executive, see the
> attachment.  It's a mixture of C and (Nasm) Assembly.  The reference was
> tiny.txt.
> 
> 
> 
>  Khoda Hafez
>  Progga
> 
> * Attached is the bootloader BOOT12.* by Jhon Fine.  It's for fat12.
> ** Also Google for this file - "CompilingBinaryFilesUsingACompiler.pdf". 
> 
> 
> 
> ------------------------------------------------------------------------
> 
> ; boot12.asm  FAT12 bootstrap for real mode image or loader
> ; Version 1.0, Jul 5, 1999
> ; Sample code
> ; by John S. Fine  johnfine@erols.com
> ; I do not place any restrictions on your use of this source code
> ; I do not provide any warranty of the correctness of this source code
> ;_____________________________________________________________________________
> ;
> ; Documentation:
> ;
> ; I)    BASIC features
> ; II)   Compiling and installing
> ; III)  Detailed features and limits
> ; IV)   Customization
> ;_____________________________________________________________________________
> ;
> ; I)    BASIC features
> ;
> ;    This boot sector will load and start a real mode image from a file in the
> ; root directory of a FAT12 formatted floppy or partition.
> ;
> ;    Inputs:
> ; DL = drive number
> ;
> ;    Outputs:
> ; The boot record is left in memory at 7C00 and the drive number is patched
> ; into the boot record at 7C24.
> ; SS = DS = 0
> ; BP = 7C00
> ;_____________________________________________________________________________
> ;
> ; II)   Compiling and installing
> ;
> ;  To compile, use NASM
> ;
> ;  nasm boot12.asm -o boot12.bin
> ;
> ;  Then you must copy the first three bytes of BOOT12.BIN to the first three
> ;  bytes of the volume and copy bytes 0x3E through 0x1FF of BOOT12.BIN to
> ;  bytes 0x3E through 0x1FF of the volume.  Bytes 0x3 through 0x3D of the
> ;  volume should be set by a FAT12 format program and should not be modified
> ;  when copying boot12.bin to the volume.
> ;
> ;  If you use my PARTCOPY program to install BOOT12.BIN on A:, the
> ;  commands are:
> ;
> ;  partcopy boot12.bin 0 3 -f0
> ;  partcopy boot12.bin 3e 1c2 -f0 3e
> ;
> ;  PARTCOPY can also install to a partition on a hard drive.  Please read
> ;  partcopy documentation and use it carefully.  Careless use could overwrite
> ;  important parts of your hard drive.
> ;
> ;  You can find PARTCOPY and links to NASM on my web page at
> ;  http://www.erols.com/johnfine/
> ;_____________________________________________________________________________
> ;
> ; III)  Detailed features and limits
> ;
> ;   Most of the limits are stable characteristics of the volume.  If you are
> ; using boot12 in a personal project, you should check the limits before
> ; installing boot12.  If you are using boot12 in a project for general
> ; distribution, you should include an installation program which checks the
> ; limits automatically.
> ;
> ; CPU:  Supports any 8088+ CPU.
> ;
> ; Volume format:  Supports only FAT12.
> ;
> ; Sector size:  Supports only 512 bytes per sector.
> ;
> ; Drive/Partition:  Supports whole drive or any partition of any drive number
> ; supported by INT 13h.
> ;
> ; Diskette parameter table:  This code does not patch the diskette parameter
> ; table.  If you boot this code from a diskette that has more sectors per
> ; track than the default initialized by the BIOS then the failure to patch
> ; that table may be a problem.  Because this code splits at track boundaries
> ; a diskette with fewer sectors per track should not be a problem.
> ;
> ; File position:  The file name may be anywhere in the root directory and the
> ; file may be any collection of clusters on the volume.  There are no
> ; contiguity requirements.  (But see track limit).
> ;
> ; Track boundaries:  Transfers are split on track boundaries.  Many BIOS's
> ; require that the caller split floppy transfers on track boundaries.
> ;
> ; 64Kb boundaries:  Transfers are split on 64Kb boundaries.  Many BIOS's
> ; require that the caller split floppy transfers on track boundaries.
> ;
> ; Cluster boundaries:  Transfers are merged across cluster boundaries whenever
> ; possible.  On some systems, this significantly reduces load time.
> ;
> ; Cluster 2 limit:  Cluster 2 must start before sector 65536 of the volume.
> ; This is very likely because only the reserved sectors (usually 1) and
> ; the FAT's (two of up to 12 sectors each) and the root directory (usually
> ; either 15 or 32 sectors) precede cluster 2.
> ;
> ; Track limit:  The entire image file must reside before track 32768 of the
> ; entire volume.  This is true on most media up to 1GB in size.  If it is a
> ; problem it is easy to fix (see boot16.asm).  I didn't expect many people
> ; to put FAT12 partitions beyond the first GB of a large hard drive.
> ;
> ; Memory boundaries:  The FAT, Root directory, and Image must all be loaded
> ; starting at addresses that are multiples of 512 bytes (32 paragraphs).
> ;
> ; Memory use:  The FAT and Root directory must each fit entirely in the
> ; first 64Kb of RAM.  They may overlap.
> ;
> ; Root directory size:  As released, it supports up to 928 entries in the
> ; root directory.  If ROOT_SEG were changed to 0x7E0 it would support up
> ; to 1040.  Most FAT12 volumes have either 240 or 512 root directory
> ; entries.
> ;_____________________________________________________________________________
> ;
> ; IV)   Customization
> ;
> ;   The memory usage can be customized by changing the _SEG variables (see
> ; directly below).
> ;
> ;   The file name to be loaded and the message displayed in case of error
> ; may be customized (see end of this file).
> ;
> ;   The ouput values may be customized.  For example, many loaders expect the
> ; bootsector to leave the drive number in DL.  You could add "mov dl,[drive]"
> ; at the label "eof:".
> ;
> ;   Some limits (like maximum track) may be removed.  See boot16.asm for
> ; comparison.
> ;
> ;   Change whatever else you like.  The above are just likely possibilities.
> ;_____________________________________________________________________________
> 
> 
> ; Change the _SEG values to customize memory use during the boot.
> ; When planning memory use, remember:
> ;
> ; *)  Each of ROOT_SEG, FAT_SEG, and IMAGE_SEG must be divisible by 0x20
> ;
> ; *)  None of ROOT, FAT or IMAGE should overlap the boot code itself, or
> ;     its stack.  That means: avoid paragraphs 0x7B0 to 0x7DF.
> ;
> ; *)  The FAT area must not overlap the IMAGE area.  Either may overlap
> ;     the ROOT area;  But, if they do then the root will not remain in
> ;     memory for possible reuse by the next stage.
> ;
> ; *)  The FAT area and the root area must each fit within the first 64Kb
> ;     excluding BIOS area (paragraphs 0x60 to 0xFFF).
> ;
> ; *)  A FAT12 FAT can be up to 6Kb (0x180 paragraphs).
> ;
> ; *)  A FAT12 root directory is typically either 0x1E0 or 0x400 paragraphs
> ;     long, but larger sizes are possible.
> ;
> ; *)  The code will be two bytes shorter when FAT_SEG is 0x800 than when it
> ;     is another value.  (If you reach the point of caring about two bytes).
> ;
> %define ROOT_SEG	0x60
> %define FAT_SEG		0x800
> %define IMAGE_SEG	0x900
> 
> %if ROOT_SEG & 31
>   %error "ROOT_SEG must be divisible by 0x20"
> %endif
> %if ROOT_SEG > 0xC00
>   %error "Root directory must fit within first 64Kb"
> %endif
> %if FAT_SEG & 31
>   %error "FAT_SEG must be divisible by 0x20"
> %endif
> %if FAT_SEG > 0xE80
>   %error "FAT must fit within first 64Kb"
> %endif
> %if IMAGE_SEG & 31
>   %error "IMAGE_SEG must be divisible by 0x20"
> %endif
> 
> ; The following %define directives declare the parts of the FAT12 "DOS BOOT
> ; RECORD" that are used by this code, based on BP being set to 7C00.
> ;
> %define	sc_p_clu	bp+0Dh		;byte  Sectors per cluster
> %define	sc_b4_fat	bp+0Eh		;word  Sectors (in partition) before FAT
> %define	fats		bp+10h		;byte  Number of FATs
> %define dir_ent		bp+11h		;word  Number of root directory entries
> %define	sc_p_fat	bp+16h		;word  Sectors per FAT
> %define sc_p_trk	bp+18h		;word  Sectors per track
> %define heads		bp+1Ah		;word  Number of heads
> %define sc_b4_prt	bp+1Ch		;dword Sectors before partition
> %define drive		bp+24h		;byte  Drive number
> 
> 	org	0x7C00
> 
> entry:
> 	jmp	short begin
> 	nop
> 
> ; Skip over the data portion of the "DOS BOOT RECORD".  The install method
> ; must merge the code from this ASM with the data put in the boot record
> ; by the FAT12 formatter.
> ;
> 	times 0x3B db 0
> 
> begin:
> 	xor	ax, ax
> 	mov	ds, ax
> 	mov	ss, ax
> 	mov	sp, 0x7C00
> 	mov	bp, sp
> 	mov	[drive], dl	;Drive number
> 
> 	mov	al, [fats]	;Number of FATs
> 	mul	word [sc_p_fat]	; * Sectors per FAT
> 	add	ax, [sc_b4_fat]	; + Sectors before FAT
> 				;AX = Sector of Root directory
> 
> 	mov	si, [dir_ent]	;Max root directory entries
> 	mov	cl, 4
> 	dec	si
> 	shr	si, cl
> 	inc	si		;SI = Length of root in sectors
> 
> 	mov	di, ROOT_SEG/32	;Buffer (paragraph / 32)
> 	call	read_16		;Read root directory
> 	push	ax		;Sector of cluster two
> %define sc_clu2 bp-2		;Later access to the word just pushed is via bp
> 
> 	mov	dx, [dir_ent]	;Number of directory entries
> 	push	ds
> 	pop	es
> 	mov	di, ROOT_SEG*16
> 
> search:
> 	dec	dx		;Any more directory entries?
> 	js	error		;No
> 	mov	si, filename	;Name we are searching for
> 	mov	cx, 11		;11 characters long
> 	lea	ax, [di+0x20]	;Precompute next entry address
> 	push	ax
> 	repe cmpsb		;Compare
> 	pop	di
> 	jnz	search		;Repeat until match
> 
> 	push word [di-6]	;Starting cluster number
> 
> 	mov	ax, [sc_b4_fat]	;Sector number of FAT
> 	mov	si, [sc_p_fat]	;Length of FAT
> 	mov	di, FAT_SEG/32	;Buffer (paragraph / 32)
> 	call	read_16		;Read FAT
> 
> next:
> 	pop	bx		;Cluster number
> 	mov	si, bx		;First cluster in this sequence
> 	mov	ax, bx		;Last cluster in this sequence
> 
> .0:
> 	cmp	bx, 0xFF8	;End of file?
> 	jae	.2		; Yes
> 	inc	ax		;Last cluster plus one in sequence
> 
> 	;Look in FAT for next cluster
> 	mov	di, bx		;Cluster number
> 	rcr	bx, 1		;1.5 byte entry per cluster
> 				;bx = 0x8000 + cluster/2
> 				;c-bit set for odd clusters
> 
> 	mov	bx, [bx+di+FAT_SEG*16-0x8000]
> 	jnc	.1
> 	shr	bx, 1
> 	shr	bx, 1
> 	shr	bx, 1
> 	shr	bx, 1
> .1:	and	bh, 0xF
> 
> 	cmp	ax, bx		;Is the next one contiguous?
> 	je	.0		;Yes: look further ahead
> .2:	sub	ax, si		;How many contiguous in this sequence?
> 	jz	eof		;None, must be done.
> 
> 	push	bx		;Save next (eof or discontiguous) cluster
> 	
> 	mov	bl, [sc_p_clu]	;Sectors per cluster
> 	mov	bh, 0		;  as a word
> 	mul	bx		;Length of sequence in sectors
> .3:	mov	di, IMAGE_SEG/32 ;Destination (paragraph / 32)
> 	add	[.3+1], ax	 ;Precompute next destination
> 	xchg	ax, si		;AX = starting cluster ;SI = length in sectors
> 	dec	ax
> 	dec	ax		;Starting cluster minus two
> 	mul	bx		; * sectors per cluster
> 	add	ax, [sc_clu2]	; + sector number of cluster two
> 	adc	dl, dh		;Allow 24-bit result
> 
> 	call	read_32		;Read it
> 	jmp	short next	;Look for more
> 
> eof:
> 	jmp	IMAGE_SEG:0
> 
> error:	mov	si, errmsg	;Same message for all detected errors
> 	mov	ax, 0xE0D	;Start message with CR
> 	mov	bx, 7
> .1:	int	10h
> 	lodsb
> 	test	al, al
> 	jnz	.1
> 	xor	ah, ah
> 	int	16h		;Wait for a key
> 	int	19h		;Try to reboot
> 
> read_16:
> 	xor	dx, dx
> 
> read_32:
> ;
> ; Input:
> ;    dx:ax = sector within partition
> ;    si    = sector count
> ;    di    = destination segment / 32
> ;
> ; The sector number is converted from a partition-relative to a whole-disk
> ; (LBN) value, and then converted to CHS form, and then the sectors are read
> ; into (di*32):0.
> ;
> ; Output:
> ;    dx:ax  updated (sector count added)
> ;    di     updated (sector count added)
> ;    si = 0
> ;    bp, ds preserved
> ;    bx, cx, es modified
> 
> .1:	push	dx			;(high) relative sector
> 	push	ax			;(low) relative sector
> 
> 	add	ax, [sc_b4_prt]		;Convert to LBN
> 	adc	dx, [sc_b4_prt+2]
> 
> 	mov	bx, [sc_p_trk]		;Sectors per track
> 	div	bx			;AX = track ;DX = sector-1
> 	sub	bx, dx			;Sectors remaining, this track
> 	cmp	bx, si			;More than we want?
> 	jbe	.2			;No
> 	mov	bx, si			;Yes: Transfer just what we want
> .2:	inc	dx			;Sector number
> 	mov	cx, dx			;CL = sector ;CH = 0
> 	cwd				;(This supports up to 32767 tracks
> 	div	word [heads]		;Track number / Number of heads
> 	mov	dh, dl			;DH = head
> 
> 	xchg	ch, al			;CH = (low) cylinder  ;AL=0
> 	ror	ah, 1			;rotate (high) cylinder
> 	ror	ah, 1
> 	add	cl, ah			;CL = combine: sector, (high) cylinder
> 
> 	sub	ax, di
> 	and	ax, byte 0x7F		;AX = sectors to next 64Kb boundary
> 	jz	.3			;On a 64Kb boundary already
> 	cmp	ax, bx			;More than we want?
> 	jbe	.4			;No
> .3:	xchg	ax, bx			;Yes: Transfer just what we want
> .4:	push	ax			;Save length
> 	mov	bx, di			;Compute destination seg
> 	push	cx
> 	mov	cl, 5
> 	shl	bx, cl
> 	pop	cx
> 	mov	es, bx
> 	xor	bx, bx			;ES:BX = address
> 	mov	dl, [drive]		;DL = Drive number
> 	mov	ah, 2			;AH = Read command
> 	int	13h			;Do it
> 	jc	error
> 	pop	bx			;Length
> 	pop	ax			;(low) relative sector
> 	pop	dx			;(high) relative sector
> 	add	ax, bx			;Update relative sector
> 	adc	dl, dh
> 	add	di, bx			;Update destination
> 	sub	si, bx			;Update count
> 	jnz	.1			;Read some more
> 	ret
> 
> errmsg	db	10,"Error Executing FAT12 bootsector",13
> 	db	10,"Press any key to reboot",13,10,0
> 
> size	equ	$ - entry
> %if size+11+2 > 512
>   %error "code is too large for boot sector"
> %endif
> 	times	(512 - size - 11 - 2) db 0
> 
> filename db	"LOADER  BIN"		;11 byte name
> 	db	0x55, 0xAA		;2  byte boot signature
> 
> 
> ------------------------------------------------------------------------
> 
> The smallest pmode + C program I could write is shown below,
> in three files. I compiled with GCC, not GPP, and got no
> warnings.
> 
> This code doesn't check for a 32-bit CPU or V86 mode. If you
> try to run it inside a DOS box, Windows will kill it.
> 
> load.asm is assembled to aout format instead of COFF, because
> DJGPP COFF doesn't let you mix 16- and 32-bit code.
> 
> ;/****************************************************************************
> ;       file load.asm
> ;****************************************************************************/
> [SECTION .text]
> [BITS 16]
> [GLOBAL start]
> start:  xor ebx,ebx             ; now in real mode (16-bit)
> 	mov bx,cs
> 	shl ebx,4
> 	mov eax,ebx		; EAX=EBX=CS<<4
> 	lea eax,[ebx]
> 	mov [gdt2 + 2],ax	; set descriptor base address=EAX
> 	mov [gdt3 + 2],ax
> 	shr eax,16
> 	mov [gdt2 + 4],al
> 	mov [gdt3 + 4],al
> 	mov [gdt2 + 7],ah
> 	mov [gdt3 + 7],ah
> 	lea eax,[ebx + gdt]	; point gdt_ptr to the gdt
> 	mov [gdt_ptr + 2],eax	; EAX=linear address of gdt
> 	push dword 0		; zero EFLAGS (interrupts off,
> 	popfd			;  IOPL=0, NT bit=0)
> 	lgdt [gdt_ptr]
> 	mov eax,cr0
> 	or al,1
> 	mov cr0,eax
> 	jmp SYS_CODE_SEL:do_pm
> [BITS 32]
> do_pm:  mov ax,SYS_DATA_SEL     ; now in 32-bit pmode
> 	mov ds,eax		; EAX works, one byte smaller :)
> 	mov ss,eax
>         nop
> 	mov es,eax
> 	mov fs,eax
> 	mov gs,eax
> 	xor eax,eax		; zero top 16 bits of ESP
> 	mov ax,sp
> 	mov esp,eax
> [EXTERN _main]
> 	call _main		; call C code
> 	jmp $			; freeze
> 
> [SECTION .data]
> ; null descriptor
> gdt:	dw 0			; limit 15:0
> 	dw 0			; base 15:0
> 	db 0			; base 23:16
> 	db 0			; type
> 	db 0			; limit 19:16, flags
> 	db 0			; base 31:24
> ; linear data segment descriptor
> LINEAR_SEL	equ	$-gdt
>         dw 0xFFFF               ; limit 0xFFFFF (1 meg? 4 gig?)
> 	dw 0			; base for this one is always 0
> 	db 0
> 	db 0x92			; present,ring 0,data,expand-up,writable
>         db 0xCF                 ; page-granular (4 gig limit), 32-bit
> 	db 0
> ; code segment descriptor
> SYS_CODE_SEL	equ	$-gdt
> gdt2:	dw 0xFFFF
> 	dw 0			; (base gets set above)
> 	db 0
> 	db 0x9A			; present,ring 0,code,non-conforming,readable
> 	db 0xCF
> 	db 0
> ; data segment descriptor
> SYS_DATA_SEL	equ	$-gdt
> gdt3:	dw 0xFFFF
> 	dw 0			; (base gets set above)
> 	db 0
> 	db 0x92			; present,ring 0,data,expand-up,writable
> 	db 0xCF
> 	db 0
> gdt_end:
> 
> gdt_ptr:
> 	dw gdt_end - gdt - 1	; GDT limit
> 	dd gdt			; linear, physical address of GDT
> 
> ;/****************************************************************************
> ;       file hello.c
> ;****************************************************************************/
> #include <string.h> /* movedata() */
> 
> #define	LINEAR_SEL	0x08
> #define	SYS_DATA_SEL	0x18
> 
> int main(void)
> {
> 	const char Msg[] = "h e l l o ";
> 
> 	movedata(SYS_DATA_SEL, (unsigned)Msg,
> 		LINEAR_SEL, 0xB8000,
> 		sizeof(Msg));
> 	return 0;
> }
> 
> ;/****************************************************************************
> ;	file build.bat
> ;*****************************************************************************/
> nasm -f aout -o load.o load.asm
> gcc -c -O2 -Wall -g -o hello.o hello.c
> ld -o pm.com -oformat binary -Ttext=0x100 load.o hello.o /djgpp/lib/libc.a
> 
HI,

I WANT TO KNOW HOW TO BOOT IN QUICKER TIME IS IT POSSIBLE.


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2004-12-11  7:15 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-07-05 13:49 Boot code in C kaushal
2004-07-05 17:36 ` John T. Williams
2004-07-06  5:26 ` Progga
2004-12-11  7:15   ` itmncm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).