Home | History | Annotate | Download | only in core
      1 /* -----------------------------------------------------------------------
      2  *
      3  *   Copyright 1999-2008 H. Peter Anvin - All Rights Reserved
      4  *
      5  *   This program is free software; you can redistribute it and/or modify
      6  *   it under the terms of the GNU General Public License as published by
      7  *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
      8  *   Boston MA 02110-1301, USA; either version 2 of the License, or
      9  *   (at your option) any later version; incorporated herein by reference.
     10  *
     11  * -----------------------------------------------------------------------
     12  */
     13 #include <sys/cpu.h>
     14 #include <sys/io.h>
     15 #include <string.h>
     16 #include <core.h>
     17 #include <fs.h>
     18 #include <bios.h>
     19 #include <syslinux/video.h>
     20 
     21 /*
     22  * localboot.c
     23  *
     24  * Boot from a local disk, or invoke INT 18h.
     25  */
     26 
     27 #define LOCALBOOT_MSG	"Booting from local disk..."
     28 
     29 #define retry_count	16
     30 
     31 extern void local_boot16(void);
     32 
     33 /*
     34  * Boot a specified local disk.  AX specifies the BIOS disk number; or
     35  * -1 in case we should execute INT 18h ("next device.")
     36  */
     37 __export void local_boot(int16_t ax)
     38 {
     39 	com32sys_t ireg, oreg;
     40 	int i;
     41 
     42         memset(&ireg, 0, sizeof(ireg));
     43 	syslinux_force_text_mode();
     44 
     45 	writestr(LOCALBOOT_MSG);
     46 	crlf();
     47 	cleanup_hardware();
     48 
     49 	if (ax == -1) {
     50 		/* Hope this does the right thing */
     51 		__intcall(0x18, &zero_regs, NULL);
     52 
     53 		/* If we returned, oh boy... */
     54 		kaboom();
     55 	}
     56 
     57 	/*
     58 	 * Load boot sector from the specified BIOS device and jump to
     59 	 * it.
     60 	 */
     61 	memset(&ireg, 0, sizeof ireg);
     62 	ireg.edx.b[0] = ax & 0xff;
     63 	ireg.eax.w[0] = 0;	/* Reset drive */
     64 	__intcall(0x13, &ireg, NULL);
     65 
     66 	memset(&ireg, 0, sizeof(ireg));
     67 	ireg.eax.w[0] = 0x0201;	/* Read one sector */
     68 	ireg.ecx.w[0] = 0x0001;	/* C/H/S = 0/0/1 (first sector) */
     69 	ireg.ebx.w[0] = OFFS(trackbuf);
     70 	ireg.es = SEG(trackbuf);
     71 
     72 	for (i = 0; i < retry_count; i++) {
     73 		__intcall(0x13, &ireg, &oreg);
     74 
     75 		if (!(oreg.eflags.l & EFLAGS_CF))
     76 			break;
     77 	}
     78 
     79 	if (i == retry_count)
     80 		kaboom();
     81 
     82 	cli();			/* Abandon hope, ye who enter here */
     83 	memcpy((void *)0x07C00, trackbuf, 512);
     84 
     85 	ireg.esi.w[0] = OFFS(trackbuf);
     86 	ireg.edi.w[0] = 0x07C00;
     87 	ireg.edx.w[0] = ax;
     88 	call16(local_boot16, &ireg, NULL);
     89 }
     90 
     91 void pm_local_boot(com32sys_t *regs)
     92 {
     93 	local_boot(regs->eax.w[0]);
     94 }
     95