Mon 14 Oct 23:06:38 CEST 2024
This commit is contained in:
		
							parent
							
								
									45aa067b85
								
							
						
					
					
						commit
						eb18aae083
					
				
							
								
								
									
										187
									
								
								kernel/bootblock.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								kernel/bootblock.S
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,187 @@ | ||||||
|  | # Copyright (C) 2015 The University of Notre Dame | ||||||
|  | # This software is distributed under the GNU General Public License. | ||||||
|  | # See the file LICENSE for details. | ||||||
|  | 
 | ||||||
|  | # This is the raw bootblock code, a 512-byte chunk of assembly | ||||||
|  | # found on the first sector of the boot disk.  The BIOS is responsible | ||||||
|  | # for starting the machine, loading this sector into memory, | ||||||
|  | # and then transferring control here.  The bootblock must call | ||||||
|  | # to the BIOS to load the remaining sectors containing the | ||||||
|  | # kernel code, and then jump there. | ||||||
|  | 
 | ||||||
|  | # Constants describing our basic memory layout are in this | ||||||
|  | # header file, which is shared between C and assembly modules: | ||||||
|  | 	 | ||||||
|  | #include "memorylayout.h" | ||||||
|  | 	 | ||||||
|  | # When we receive control from the BIOS, the following are set: | ||||||
|  | # %dl - the device number this block was loaded from | ||||||
|  | # %es:%si - the partition table entry we were loaded from | ||||||
|  | 
 | ||||||
|  | # To set the code segment appropriately, the first thing we | ||||||
|  | # do is a long jump to _start2, which sets cs=BOOTBLOCK_SEGMENT | ||||||
|  | 	 | ||||||
|  | .code16 | ||||||
|  | .text | ||||||
|  | .global _start
 | ||||||
|  | _start: | ||||||
|  | 	ljmp	$BOOTBLOCK_SEGMENT,$_start2 | ||||||
|  | 
 | ||||||
|  | # Now we begin setting up the execution environment | ||||||
|  | # for loading the rest of the kernel. | ||||||
|  | 
 | ||||||
|  | _start2:	 | ||||||
|  | 	sti				# disable interrupts | ||||||
|  | 	cld				# clear the direction flag | ||||||
|  | 	mov	%cs, %ax		# set all segments to code | ||||||
|  | 	mov	%ax, %ds | ||||||
|  | 	mov	%ax, %es | ||||||
|  | 	mov	$INTERRUPT_STACK_SEGMENT, %ax     # set up the stack | ||||||
|  | 	mov	%ax, %ss | ||||||
|  | 	mov	$INTERRUPT_STACK_OFFSET, %sp | ||||||
|  | 
 | ||||||
|  | 	mov	%dl, (disk_number)	# save the disk number | ||||||
|  | 	mov	partition_status,%di	# set the partition table as dest | ||||||
|  | 	mov	$12, %cx		# copy 12 bytes from si to di | ||||||
|  | 	rep	movsb | ||||||
|  | 		 | ||||||
|  | 	mov	$(loadmsg),%si		# print initial message | ||||||
|  |         call	bios_putstring | ||||||
|  | 
 | ||||||
|  | 	mov	$0,%ah			# reset the disk system | ||||||
|  | 	int	$0x13 | ||||||
|  | 
 | ||||||
|  | 	mov	$0x08, %ah		# get the drive geometry | ||||||
|  | 	int	$0x13 | ||||||
|  | 	and	$0x3f, %cl		# mask off high tracks | ||||||
|  | 	mov	%cl, (disk_sectors) | ||||||
|  | 	mov	%ch, (disk_cylinders) | ||||||
|  | 	mov	%dh, (disk_heads) | ||||||
|  | 	 | ||||||
|  | 	mov	$KERNEL_SEGMENT,%ax	# load happens at es:bx | ||||||
|  | 	mov	%ax, %es		# which we set to | ||||||
|  | 	mov	$KERNEL_OFFSET,%bx	# KERNEL_SEGMENT:KERNEL_OFFSET | ||||||
|  | 
 | ||||||
|  | 					# disk parameters: | ||||||
|  | 	mov	(disk_number), %dl	#	device | ||||||
|  | 	mov	$0,%ch			#	cylinder 0 | ||||||
|  | 	mov	$0,%dh			#	head 0 | ||||||
|  | 	mov	$2,%cl			#	sector 2 | ||||||
|  | 
 | ||||||
|  | loadsector: | ||||||
|  | 	mov	$1,%al			# load 1 sector | ||||||
|  | 	mov	$0x02, %ah		# load command | ||||||
|  | 	int	$0x13			# execute load | ||||||
|  | 	 | ||||||
|  | 	mov	$'.', %al		# display a dot | ||||||
|  | 	call	bios_putchar		# for each sector loaded | ||||||
|  | 	 | ||||||
|  | 	mov	(sectors_left),%ax	# how many sectors left? | ||||||
|  | 	cmp	$0xffff, %ax		# has it been initialized? | ||||||
|  | 	jne	gotsectors		# yes - use the value | ||||||
|  | 	mov	%es:(KERNEL_SIZE_OFFSET),%eax	# no - get size of kernel | ||||||
|  | 	shr	$9, %eax		# convert into blocks | ||||||
|  | 	inc	%eax			# add one for good measure | ||||||
|  | 	 | ||||||
|  | gotsectors:		 | ||||||
|  | 	dec	%ax			# remove one block | ||||||
|  | 	mov	%ax,(sectors_left)	# store the value | ||||||
|  | 	cmp	$0, %ax			# are we done? | ||||||
|  | 	je	loaddone		# yes - jump to bottom | ||||||
|  | 			 | ||||||
|  | checksegment: | ||||||
|  | 	add	$512,%bx		# move data pointer by 512 bytes | ||||||
|  | 	cmp	$0, %bx			# did we reach segment end? | ||||||
|  | 	jnz	nextsector		# no - find next sector | ||||||
|  | 	mov	%es, %ax		# yes - retrieve seg register | ||||||
|  | 	add	$0x1000, %ax		# move to next 64k block | ||||||
|  | 	mov	%ax, %es		# store segment register | ||||||
|  | 
 | ||||||
|  | nextsector: | ||||||
|  | 	inc	%cl			# advance by one sector | ||||||
|  | 	mov	(disk_sectors),%al	# what is the maximum sector? | ||||||
|  | 	cmp	%al, %cl		# is this the last sector? | ||||||
|  | 	jle	loadsector		# no - load the next sector | ||||||
|  | 	mov	$1,%cl			# yes - go to sector zero.. | ||||||
|  | 
 | ||||||
|  | 	inc	%dh			# advance to next head | ||||||
|  | 	mov	(disk_heads), %al	# what is the maximum head? | ||||||
|  | 	cmp	%al, %dh		# is this the last head? | ||||||
|  | 	jle	loadsector		# no - read the next sector | ||||||
|  | 	mov	$0,%dh			# yes - go to head zero | ||||||
|  | 
 | ||||||
|  | 	inc	%ch			# advance to next cylinder | ||||||
|  | 	mov	(disk_cylinders), %al	# what is the maximum cylinder? | ||||||
|  | 	cmp	%al, %ch		# is this the last cylinder? | ||||||
|  | 	jle	loadsector		# no - read the next sector | ||||||
|  | 					# yes - fall through here | ||||||
|  | loaddone: | ||||||
|  | 	mov	$0,%ah			# reset the disk system | ||||||
|  | 	int	$0x13 | ||||||
|  | 	 | ||||||
|  | 	mov	$(bootmsg),%si		# print boot message | ||||||
|  |         call	bios_putstring | ||||||
|  | 	 | ||||||
|  | 	mov	$KERNEL_SEGMENT, %ax    # jump to the kernel code | ||||||
|  | 	mov	%ax, %ds | ||||||
|  | 	ljmp	$KERNEL_SEGMENT, $KERNEL_OFFSET | ||||||
|  | 	 | ||||||
|  | bios_putstring:				# routine to print an entire string | ||||||
|  | 	mov	(%si), %al | ||||||
|  | 	cmp	$0, %al | ||||||
|  | 	jz	bios_putstring_done | ||||||
|  |         call	bios_putchar | ||||||
|  | 	inc	%si | ||||||
|  | 	jmp	bios_putstring | ||||||
|  | bios_putstring_done: | ||||||
|  |         ret | ||||||
|  | 
 | ||||||
|  | bios_putchar:				# routine to print a single char | ||||||
|  | 	push	%ax | ||||||
|  | 	push	%bx | ||||||
|  |         mov	$14,%ah | ||||||
|  |         mov	$1,%bl | ||||||
|  |         int	$0x10 | ||||||
|  | 	pop	%bx | ||||||
|  | 	pop	%ax | ||||||
|  | 	ret | ||||||
|  | 
 | ||||||
|  | loadmsg: | ||||||
|  |         .asciz "bootblock: loading kernel...\r\n" | ||||||
|  | bootmsg: | ||||||
|  | 	.asciz "\r\nbootblock: booting kernel...\r\n" | ||||||
|  | 
 | ||||||
|  | disk_number: | ||||||
|  | 	.byte 0
 | ||||||
|  | disk_cylinders: | ||||||
|  | 	.byte 0
 | ||||||
|  | disk_heads: | ||||||
|  | 	.byte 0
 | ||||||
|  | disk_sectors: | ||||||
|  | 	.byte 0
 | ||||||
|  | sectors_left:	 | ||||||
|  | 	.word 0xffff
 | ||||||
|  | 
 | ||||||
|  | partition_status: | ||||||
|  | 	.byte 0
 | ||||||
|  | partition_start_chs:	 | ||||||
|  | 	.byte 0
 | ||||||
|  | 	.byte 0
 | ||||||
|  | 	.byte 0
 | ||||||
|  | partition_type:	 | ||||||
|  | 	.byte 0
 | ||||||
|  | partition_stop_chs:	 | ||||||
|  | 	.byte 0
 | ||||||
|  | 	.byte 0
 | ||||||
|  | 	.byte 0
 | ||||||
|  | partition_start_lba: | ||||||
|  | 	.long 0
 | ||||||
|  | partition_length: | ||||||
|  | 	.long 0
 | ||||||
|  | 				 | ||||||
|  | # A bootblock must have 0xaa55 in its two final bytes. | ||||||
|  | # The .org directive forces this data to that point. | ||||||
|  | 
 | ||||||
|  | .org 510
 | ||||||
|  | bootflag: | ||||||
|  | 	.word 0xaa55
 | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user