bootsector.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020 
00021 /**
00022  * @file
00023  *
00024  * x86 bootsector image format
00025  *
00026  */
00027 
00028 #include <errno.h>
00029 #include <realmode.h>
00030 #include <biosint.h>
00031 #include <bootsector.h>
00032 
00033 /** Vector for storing original INT 18 handler
00034  *
00035  * We do not chain to this vector, so there is no need to place it in
00036  * .text16.
00037  */
00038 static struct segoff int18_vector;
00039 
00040 /** Vector for storing original INT 19 handler
00041  *
00042  * We do not chain to this vector, so there is no need to place it in
00043  * .text16.
00044  */
00045 static struct segoff int19_vector;
00046 
00047 /** Restart point for INT 18 or 19 */
00048 extern void bootsector_exec_fail ( void );
00049 
00050 /**
00051  * Jump to preloaded bootsector
00052  *
00053  * @v segment           Real-mode segment
00054  * @v offset            Real-mode offset
00055  * @v drive             Drive number to pass to boot sector
00056  * @ret rc              Return status code
00057  */
00058 int call_bootsector ( unsigned int segment, unsigned int offset,
00059                       unsigned int drive ) {
00060         int discard_b, discard_D, discard_d;
00061 
00062         DBG ( "Booting from boot sector at %04x:%04x\n", segment, offset );
00063 
00064         /* Hook INTs 18 and 19 to capture failure paths */
00065         hook_bios_interrupt ( 0x18, ( unsigned int ) bootsector_exec_fail,
00066                               &int18_vector );
00067         hook_bios_interrupt ( 0x19, ( unsigned int ) bootsector_exec_fail,
00068                               &int19_vector );
00069 
00070         /* Boot the loaded sector
00071          *
00072          * We assume that the boot sector may completely destroy our
00073          * real-mode stack, so we preserve everything we need in
00074          * static storage.
00075          */
00076         __asm__ __volatile__ ( REAL_CODE ( /* Save return address off-stack */
00077                                            "popw %%cs:saved_retaddr\n\t"
00078                                            /* Save stack pointer */
00079                                            "movw %%ss, %%ax\n\t"
00080                                            "movw %%ax, %%cs:saved_ss\n\t"
00081                                            "movw %%sp, %%cs:saved_sp\n\t"
00082                                            /* Jump to boot sector */
00083                                            "pushw %%bx\n\t"
00084                                            "pushw %%di\n\t"
00085                                            "sti\n\t"
00086                                            "lret\n\t"
00087                                            /* Preserved variables */
00088                                            "\nsaved_ss: .word 0\n\t"
00089                                            "\nsaved_sp: .word 0\n\t"
00090                                            "\nsaved_retaddr: .word 0\n\t"
00091                                            /* Boot failure return point */
00092                                            "\nbootsector_exec_fail:\n\t"
00093                                            /* Restore stack pointer */
00094                                            "movw %%cs:saved_ss, %%ax\n\t"
00095                                            "movw %%ax, %%ss\n\t"
00096                                            "movw %%cs:saved_sp, %%sp\n\t"
00097                                            /* Return via saved address */
00098                                            "jmp *%%cs:saved_retaddr\n\t" )
00099                                : "=b" ( discard_b ), "=D" ( discard_D ),
00100                                  "=d" ( discard_d )
00101                                : "b" ( segment ), "D" ( offset ),
00102                                  "d" ( drive )
00103                                : "eax", "ecx", "esi", "ebp" );
00104 
00105         DBG ( "Booted disk returned via INT 18 or 19\n" );
00106 
00107         /* Unhook INTs 18 and 19 */
00108         unhook_bios_interrupt ( 0x18, ( unsigned int ) bootsector_exec_fail,
00109                                 &int18_vector );
00110         unhook_bios_interrupt ( 0x19, ( unsigned int ) bootsector_exec_fail,
00111                                 &int19_vector );
00112         
00113         return -ECANCELED;
00114 }

Generated on Tue Apr 6 20:00:49 2010 for gPXE by  doxygen 1.5.7.1