bobby digital
2007-Oct-17 20:58 UTC
[syslinux] Adding a "boot from local hard disk" option to syslinux menu, booted from USB
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
Dyks, Axel (XL)
2007-Oct-18 18:30 UTC
[syslinux] Adding a "boot from local hard disk" option to syslinux menu, booted from USB
bobby digital wrote:> 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.The "first" drive -- as seen be your BIOS -- when booting from a USB disk or stick, isn't your laptop's HD but the USB disk/stick. ... otherwise it would have booted from the laptop's HD. - Axel
H. Peter Anvin
2007-Oct-19 00:32 UTC
[syslinux] Adding a "boot from local hard disk" option to syslinux menu, booted from USB
bobby digital wrote:> 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??). >It sounds like when your BIOS boots from the USB disk, it hides the primary hard disk. This is pretty braindead behaviour, but I could see how it would "make sense" to someone as they implemented it. The problem is, if it doesn't make the proper hard disk available as another drive number, the only way out would be to invoke the BIOS Boot Specification interfaces, to boot a different device. Right now I don't have code for that. -hpa
bobby digital
2007-Oct-20 11:30 UTC
[syslinux] Adding a "boot from local hard disk" option to syslinux menu, booted from USB
Hi Axel, hpa, Thanks so much for your responses.> The "first" drive -- as seen be your BIOS -- whenbooting from> a USB disk or stick, isn't your laptop's HD but theUSB disk/stick.> ... otherwise it would have booted from the laptop'sHD. That is what I also thought - since "chain.c32 hd0 0" seemed to boot from the USB disk, I asummed I'd find the C drive at "hd1 0" but it failed, and so did "hd2 0" etc etc. Therefore I modified the chain.c32 code, so it accepts max drive and partition number and loops through them all, hoping to reveal an MBR - but I couldn't see any (partly because the text dissapears from screen very fast, and I couldn't get a report to save on disk :) )> It sounds like when your BIOS boots from the USBdisk, it hides the> primary hard disk. This is pretty braindeadbehaviour, but I could see> > how it would "make sense" to someone as theyimplemented it. Wow :) Never heard of this, but does make sense to me too (the laptop's a Compaq) - thanks ..> The problem is, if it doesn't make the proper harddisk available as> another drive number, the only way out would be toinvoke the BIOS> Boot Specification interfaces, to boot a differentdevice.> Right now I don't have code for that.Thanks for the info.. Maybe you'd have a link where something like that is discussed? Well, any suggestions on how to make this work would be greatly appreciated.. Thanks again b. __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com