[syslinux] Adding a "boot from local hard disk" option to syslinux menu, booted from USB

bobby digital junksmi at yahoo.com
Wed Oct 17 13:58:52 PDT 2007


Hi all, 

I use XP on my laptop PC, with 30 GB HD (single
partition), and a 3.5" hard drive (not a stick),
accessed through a USB encasing, partitioned as five
logical drives. 

I have successfully set up syslinux to boot several
Ubuntu versions from the primary USB hard drive
partition, and no problems there. The problem is, I
would like to have an entry in the menu, like "Boot
from first hard disk", in which case, I would boot XP
from the laptop hard drive. 

I'm not very knowledgeable about booting, but I read
that I would have to chainload, so I tried to use
chain.c32 and the following entries: 

LABEL hd
  menu label ^hd - boot IDE0 hd0 0
  kernel chain.c32
  append hd0 0
  
and 

LABEL hd2
  menu label ^Boot from first hard disk
  localboot 0x80
  append -

but unfortunately nothing seems to happen (the first
option says "illegal argument" or something, exits and
shows boot menu again, the other simply show the boot
menu again) - it seems as if chain.c32 interprets "hd0
0" to be a partition on the USB hard drive, instead of
the local one? 

I tried to modify the source code of chain.c32 (the
function is included below, compiled through
DSL-embedded, with gcc package) where I tried to scan
through possible hard disks (that is, loop through
drive and partition indexes) and print out info, in
hope that I'd spot the main (C) drive on the laptop.
But apart from the USB drive itself, nothing seems to
have an MBR, no matter how much I look? (it could be
easier if I could save a text report, but the file
open operation fails - I'm guessing because at the
moment, it is not known what the default drive is??).

Well, in any case, I would really appreciate if
someone can let me know if what I want to do is
possible at all with syslinux; and possibly how to do
it... 

Thanks,
Cheers


///


int main(int argc, char *argv[])
{
  char *mbr, *boot_sector = NULL;
  struct part_entry *partinfo;
  char *drivename, *partition, *endds, *endps,
*waittotals;
  int hd, drive, whichpart;
  static com32sys_t inreg;	/* In bss, so zeroed
automatically */
  int idd, idp, endd, endp; 
  FILE *f;
  char *log = "/chsdlog.txt";
  char logsc[1024];
  char *logs = &logsc;
  char logrc[10240];
  char *logr = &logrc;
  char inch[20];
  int ix = 0; 
  int waittotal; 
  char cc; 
  FILE *pFile = NULL;
  
  openconsole(&dev_null_r, &dev_stdcon_w);

  /*if ( argc < 2 ) {
    error("Usage: chain.c32 (hd|fd)# [partition]\n");
    goto bail;
  }*/

  strcpy (logrc, "Log: ");
  sprintf(logs, "Starting chainsd - chain see disk
only.\n");
  printf(logs);
  
  strcat(logrc, logs);
  
	  //drivename = argv[1];
	  //partition = argv[2];		/* Possibly null */

  endds = argv[1];
  endps = argv[2];		/* Possibly null */
  waittotals = argv[3];		/* Possibly null */

  if ( endds )
	endd = strtoul(endds, NULL, 0);
  else endd = 1; 

  if ( endps )
	endp = strtoul(endps, NULL, 0);
  else endp = 3; 
  
  if ( waittotals )
	waittotal = strtoul(waittotals, NULL, 0);
  else waittotal = 500;   
  
  sprintf(logs, "Probing hard disks: %d first disks -
%d first partitions each\n", endd, endp);
  printf(logs);
  strcat(logrc, logs);
  
  drivename = "hd0";
  partition = "0";
  
  // loop through drives and partitions
  for (idd=0; idd<=endd; idd++)
   for (idp=0; idp<=endp; idp++)
  {
	  //partition = NULL; 
	  
	  drivename[2] = 48+idd; //ascii 0 or 1
	  partition[0] = 48+idp;
	  
	  sprintf(logs, "Current: drivename %s, partition %s,
idd %d, idp %d\n", drivename, partition, idd, idp);
	  
	  printf(logs);
	  strcat(logrc, logs);	  
	  
	  hd = 0;
	  if ( (drivename[0] == 'h' || drivename[0] == 'f')
&&
		   drivename[1] == 'd' ) {
		hd = drivename[0] == 'h';
		drivename += 2;
	  }
	  drive = (hd ? 0x80 : 0) | strtoul(drivename, NULL,
0);
	  //whichpart = 0;		/* Default */
	  //whichpart = ip;
	
	  if ( partition )
		whichpart = strtoul(partition, NULL, 0);
	
	  if ( !(drive & 0x80) && whichpart ) {
		//error();
		  sprintf(logs, "Warning: Partitions of floppy
devices may not work\n");
		  error(logs);
		  strcat(logrc, logs);

	  }
	  
	  
	  sprintf(logs, "Current: %s, whichpart(ition) %d,
drive %d\n", drivename, whichpart, drive);
	  printf(logs);
	  strcat(logrc, logs);
		  
	  /* Divvy up the bounce buffer.  To keep things
sector-
		 aligned, give the EBIOS DAPA the first sector, then
		 the MBR next, and the rest is used for the
partition-
		 chasing stack. */
	  dapa = (struct ebios_dapa *)__com32.cs_bounce;
	  mbr  = (char *)__com32.cs_bounce + SECTOR;
	
	  /* Get the disk geometry (not needed for MBR) */

	  sprintf(logs, "Get the disk geometry - Calling
get_disk_params\n");
	  printf(logs);
	  strcat(logrc, logs);
	  
	  if ( get_disk_params(drive) && whichpart ) {
		//error();
		  sprintf(logs, "Cannot get disk parameters\n");
		  error(logs);
		  strcat(logrc, logs);
		goto endloop;
	  }
	
  	 
	  sprintf(logs, "disk_info: disk %d, ebios %d, cbios
%d, head %d, sect %d\n", disk_info.disk,
disk_info.ebios, disk_info.cbios, disk_info.head,
disk_info.sect);
	  printf(logs);
	  strcat(logrc, logs);
	  
	  /* Get MBR */
	  sprintf(logs, "Get MBR - Calling read_sector\n");
	  printf(logs);
	  strcat(logrc, logs);
	  
	  if ( read_sector(mbr, 0) ) {
		//error();
		  sprintf(logs, "Cannot read Master Boot Record\n");
		  error(logs);
			strcat(logrc, logs);		
		goto endloop;
	  }
	
	  sprintf(logs, "mbr: %s ...\n", mbr);
	  printf(logs);
	  strcat(logrc, logs);
	  
	  if ( whichpart == 0 ) {
		/* Boot the MBR */

		  sprintf(logs, "whichpart == 0 Boot the MBR\n");
		  printf(logs);
		  strcat(logrc, logs);
		
		partinfo = NULL;
		boot_sector = mbr;
	  } else if ( whichpart <= 4 ) {
		/* Boot a primary partition */

		  sprintf(logs, "whichpart <= 4 Boot a primary
partition\n");
		  printf(logs);
		  strcat(logrc, logs);
		
		partinfo = &((struct part_entry *)(mbr +
0x1be))[whichpart-1];
		if ( partinfo->ostype == 0 ) {
		  //error();
		  sprintf(logs, "Invalid primary partition\n");
		  error(logs);
		  strcat(logrc, logs);
		  		  
		  goto endloop;
		}
	  } else {
		/* Boot a logical partition */

		  sprintf(logs, "whichpart > 4 Boot a logical
partition \n");
		  printf(logs);
		  strcat(logrc, logs);
		
		nextpart = 5;
		partinfo = find_logical_partition(whichpart, mbr,
NULL, NULL);
	
		if ( !partinfo || partinfo->ostype == 0 ) {
		  //error();

		  sprintf(logs, "Requested logical partition not
found\n");
		  error(logs);
		  strcat(logrc, logs);
		  
		  goto endloop;
		}
	  }


	  /* Do the actual chainloading */
	  if ( partinfo ) {
		/* Actually read the boot sector */
		/* Pick the first buffer that isn't already in use
*/

		boot_sector = (char *)(((unsigned long)partinfo +
511) & ~511);
		
		  sprintf(logs, "partinfo: active_flag %d,
start_head %d, start_sect %d, start_cyl %d, ostype %d,
end_head %d, end_sect %d, end_cyl %d, start_lba %d,
length %d, boot_sector %s\n", partinfo->active_flag,
partinfo->start_head, partinfo->start_sect,
partinfo->start_cyl, partinfo->ostype,
partinfo->end_head, partinfo->end_sect,
partinfo->end_cyl, partinfo->start_lba,
partinfo->length, boot_sector);
		  printf(logs);
			strcat(logrc, logs);		
		
		
		if ( read_sector(boot_sector, partinfo->start_lba) )
{
		  //error();
		  sprintf(logs, "Cannot read boot sector\n");
		  error(logs);
		  strcat(logrc, logs);
		  
		  goto endloop;
		}
	
		/* 0x7BE is the canonical place for the first
partition entry. */
		inreg.esi.w[0] = 0x7be;
		memcpy((char *)0x7be, partinfo, sizeof(*partinfo));
	  }
  
  printf("NO Press dot . -waiting 100000 ticks\n\n");

  
  endloop:
   
  // cannot find a way to wait for a keypress, so this
way to make a pause
  ix = 0; 
  while (ix < waittotal)
  { printf("\r%d/%d waiting ticks.. ", ix, waittotal);
	ix += 1; }
  printf("\n\n");

  } //end for loops
  
  fputs("Booting...not\n", stdout);

  pFile = fopen("chreport.txt", "a");
  if(pFile == NULL)
  {
    printf("Error opening for writing. Program
terminated.");
    abort();
  }
  else
  {
	fprintf(pFile, logrc);
	fclose(pFile);
  }
  //inreg.eax.w[0] = 0x000d;	/* Clean up and chain
boot */
  //inreg.edx.w[0] = 0;		/* Should be 3 for "keeppxe"
*/
  //inreg.edi.l    = (uint32_t)boot_sector;
  //inreg.ecx.l    = SECTOR;	/* One sector */
  //inreg.ebx.b[0] = drive;	/* DL = drive no */

  //__intcall(0x22, &inreg, NULL);

  /* If we get here, badness happened */
  /*f = fopen(log, "wb");
  fwrite(logr, sizeof(char), strlen(logr), f);
  fclose(f);*/
  
  error("Chainboot failed! not - all fine, come to
end... \n");

bail:
  return 255;
}


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 




More information about the Syslinux mailing list