Home | History | Annotate | Download | only in image
      1 /*
      2  * Copyright (C) 2007 Michael Brown <mbrown (at) fensystems.co.uk>.
      3  *
      4  * This program is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU General Public License as
      6  * published by the Free Software Foundation; either version 2 of the
      7  * License, or any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful, but
     10  * WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program; if not, write to the Free Software
     16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     17  */
     18 
     19 FILE_LICENCE ( GPL2_OR_LATER );
     20 
     21 /**
     22  * @file
     23  *
     24  * x86 bootsector image format
     25  *
     26  */
     27 
     28 #include <errno.h>
     29 #include <realmode.h>
     30 #include <biosint.h>
     31 #include <bootsector.h>
     32 
     33 /** Vector for storing original INT 18 handler
     34  *
     35  * We do not chain to this vector, so there is no need to place it in
     36  * .text16.
     37  */
     38 static struct segoff int18_vector;
     39 
     40 /** Vector for storing original INT 19 handler
     41  *
     42  * We do not chain to this vector, so there is no need to place it in
     43  * .text16.
     44  */
     45 static struct segoff int19_vector;
     46 
     47 /** Restart point for INT 18 or 19 */
     48 extern void bootsector_exec_fail ( void );
     49 
     50 /**
     51  * Jump to preloaded bootsector
     52  *
     53  * @v segment		Real-mode segment
     54  * @v offset		Real-mode offset
     55  * @v drive		Drive number to pass to boot sector
     56  * @ret rc		Return status code
     57  */
     58 int call_bootsector ( unsigned int segment, unsigned int offset,
     59 		      unsigned int drive ) {
     60 	int discard_b, discard_D, discard_d;
     61 
     62 	DBG ( "Booting from boot sector at %04x:%04x\n", segment, offset );
     63 
     64 	/* Hook INTs 18 and 19 to capture failure paths */
     65 	hook_bios_interrupt ( 0x18, ( unsigned int ) bootsector_exec_fail,
     66 			      &int18_vector );
     67 	hook_bios_interrupt ( 0x19, ( unsigned int ) bootsector_exec_fail,
     68 			      &int19_vector );
     69 
     70 	/* Boot the loaded sector
     71 	 *
     72 	 * We assume that the boot sector may completely destroy our
     73 	 * real-mode stack, so we preserve everything we need in
     74 	 * static storage.
     75 	 */
     76 	__asm__ __volatile__ ( REAL_CODE ( /* Save return address off-stack */
     77 					   "popw %%cs:saved_retaddr\n\t"
     78 					   /* Save stack pointer */
     79 					   "movw %%ss, %%ax\n\t"
     80 					   "movw %%ax, %%cs:saved_ss\n\t"
     81 					   "movw %%sp, %%cs:saved_sp\n\t"
     82 					   /* Jump to boot sector */
     83 					   "pushw %%bx\n\t"
     84 					   "pushw %%di\n\t"
     85 					   "sti\n\t"
     86 					   "lret\n\t"
     87 					   /* Preserved variables */
     88 					   "\nsaved_ss: .word 0\n\t"
     89 					   "\nsaved_sp: .word 0\n\t"
     90 					   "\nsaved_retaddr: .word 0\n\t"
     91 					   /* Boot failure return point */
     92 					   "\nbootsector_exec_fail:\n\t"
     93 					   /* Restore stack pointer */
     94 					   "movw %%cs:saved_ss, %%ax\n\t"
     95 					   "movw %%ax, %%ss\n\t"
     96 					   "movw %%cs:saved_sp, %%sp\n\t"
     97 					   /* Return via saved address */
     98 					   "jmp *%%cs:saved_retaddr\n\t" )
     99 			       : "=b" ( discard_b ), "=D" ( discard_D ),
    100 			         "=d" ( discard_d )
    101 			       : "b" ( segment ), "D" ( offset ),
    102 			         "d" ( drive )
    103 			       : "eax", "ecx", "esi", "ebp" );
    104 
    105 	DBG ( "Booted disk returned via INT 18 or 19\n" );
    106 
    107 	/* Unhook INTs 18 and 19 */
    108 	unhook_bios_interrupt ( 0x18, ( unsigned int ) bootsector_exec_fail,
    109 				&int18_vector );
    110 	unhook_bios_interrupt ( 0x19, ( unsigned int ) bootsector_exec_fail,
    111 				&int19_vector );
    112 
    113 	return -ECANCELED;
    114 }
    115