linux-c-programming.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: itmncm <muruganandam@letterboxes.org>
To: linux-c-programming@vger.kernel.org
Subject: Re: Boot code in C
Date: Sat, 11 Dec 2004 12:45:13 +0530	[thread overview]
Message-ID: <cpe5po$323$1@sea.gmane.org> (raw)
In-Reply-To: <20040706112618.B358@Imrashi.net.bd>

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.


      reply	other threads:[~2004-12-11  7:15 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='cpe5po$323$1@sea.gmane.org' \
    --to=muruganandam@letterboxes.org \
    --cc=linux-c-programming@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).