mmap = syslinux_memory_map();
if (!mmap) {
- error("Cannot read system memory map\n");
+ error("Cannot read system memory map.");
return;
}
/* Force text mode */
syslinux_force_text_mode();
- fputs("Booting...\n", stdout);
+ puts("Booting...");
syslinux_shuffle_boot_rm(mlist, mmap, opt.keeppxe, &opt.regs);
- error("Chainboot failed!\n");
+ error("Chainboot failed !");
return;
too_big:
- error("Loader file too large\n");
+ error("Loader file too large.");
return;
enomem:
- error("Out of memory\n");
+ error("Out of memory.");
return;
}
if (!strncmp(opt.drivename, "mbr", 3)) {
if (find_by_sig(strtoul(opt.drivename + 4, NULL, 0), &iter) < 0) {
- error("Unable to find requested MBR signature.\n");
+ error("Unable to find requested MBR signature.");
goto bail;
}
} else if (!strncmp(opt.drivename, "guid", 4)) {
if (str_to_guid(opt.drivename + 5, &gpt_guid))
goto bail;
if (find_by_guid(&gpt_guid, &iter) < 0) {
- error("Unable to find requested GPT disk or partition by guid.\n");
+ error("Unable to find requested GPT disk or partition by guid.");
goto bail;
}
} else if (!strncmp(opt.drivename, "label", 5)) {
if (!opt.drivename[6]) {
- error("No label specified.\n");
+ error("No label specified.");
goto bail;
}
if (find_by_label(opt.drivename + 6, &iter) < 0) {
- error("Unable to find requested GPT partition by label.\n");
+ error("Unable to find requested GPT partition by label.");
goto bail;
}
} else if ((opt.drivename[0] == 'h' || opt.drivename[0] == 'f') &&
} else if (!strcmp(opt.drivename, "boot") || !strcmp(opt.drivename, "fs")) {
if (!is_phys(sdi->c.filesystem)) {
error("When syslinux is not booted from physical disk (or its emulation),\n"
- "'boot' and 'fs' are meaningless.\n");
+ "'boot' and 'fs' are meaningless.");
goto bail;
}
/* offsets match, but in case it changes in the future */
}
/* broken part structure or other problems */
if (iter->status) {
- error("Can't find myself on the drive I booted from.\n");
+ error("Can't find myself on the drive I booted from.");
goto bail;
}
}
} else {
- error("Unparsable drive specification.\n");
+ error("Unparsable drive specification.");
goto bail;
}
/* main options done - only thing left is explicit partition specification,
break;
} while (!pi_next(iter));
if (iter->status) {
- error("Requested disk / partition combination not found.\n");
+ error("Requested disk / partition combination not found.");
goto bail;
}
}
if (!(iter->di.disk & 0x80) && iter->index) {
- error("WARNING: Partitions on floppy devices may not work.\n");
+ warn("Partitions on floppy devices may not work.");
}
*_iter = iter;
/* RAW handover protocol */
ha = malloc(synth_size);
if (!ha) {
- error("Could not build RAW hand-over record!\n");
+ critm();
goto bail;
}
len = ~0u;
synth_size += sizeof *plen + iter->gpt.pe_size;
ha = malloc(synth_size);
if (!ha) {
- error("Could not build GPT hand-over record!\n");
+ critm();
goto bail;
}
lba2chs(&ha->start, &iter->di, iter->start_lba, L2C_CADD);
/* MBR handover protocol */
ha = malloc(synth_size);
if (!ha) {
- error("Could not build MBR hand-over record!\n");
+ critm();
goto bail;
}
memcpy(ha, iter->record, synth_size);
fdat.base = (opt.fseg << 4) + opt.foff;
if (loadfile(opt.file, &fdat.data, &fdat.size)) {
- error("Couldn't read the boot file.\n");
+ error("Couldn't read the boot file.");
goto bail;
}
if (fdat.base + fdat.size - 1 > ADDRMAX) {
- error("The boot file is too big to load at this address.\n");
+ error("The boot file is too big to load at this address.");
goto bail;
}
}
sdat.size = iter->di.bps;
if (sdat.base + sdat.size - 1 > ADDRMAX) {
- error("The sector cannot be loaded at such high address.\n");
+ error("The sector cannot be loaded at such high address.");
goto bail;
}
if (!(sdat.data = disk_read_sectors(&iter->di, iter->start_lba, 1))) {
- error("Couldn't read the sector.\n");
+ error("Couldn't read the sector.");
goto bail;
}
if (opt.save) {
if (!(sbck = malloc(sdat.size))) {
- error("Couldn't allocate cmp-buf for option 'save'.\n");
+ critm();
goto bail;
}
memcpy(sbck, sdat.data, sdat.size);
}
if (opt.file && opt.maps && overlap(&fdat, &sdat)) {
- error("WARNING: The sector won't be mmapped, as it would conflict with the boot file.\n");
+ warn("The sector won't be mmapped, as it would conflict with the boot file.");
opt.maps = false;
}
}
/* Verify possible conflicts */
if ( ( opt.file && overlap(&fdat, &hdat)) ||
( opt.maps && overlap(&sdat, &hdat)) ) {
- error("WARNING: Handover area won't be prepared,\n"
- "as it would conflict with the boot file and/or the sector.\n");
+ warn("Handover area won't be prepared,\n"
+ "as it would conflict with the boot file and/or the sector.");
opt.hand = false;
}
}
memcpy(data + ndata++, &hdat, sizeof(hdat));
#ifdef DEBUG
- printf("iter->di dsk, bps: %X, %u\niter->di lbacnt, C*H*S: %"PRIu64", %u\n"
+ dprintf("iter->di dsk, bps: %X, %u\niter->di lbacnt, C*H*S: %"PRIu64", %u\n"
"iter->di C, H, S: %u, %u, %u\n",
iter->di.disk, iter->di.bps,
iter->di.lbacnt, iter->di.cyl * iter->di.head * iter->di.spt,
iter->di.cyl, iter->di.head, iter->di.spt);
- printf("iter idx: %d\n", iter->index);
- printf("iter lba: %"PRIu64"\n", iter->start_lba);
+ dprintf("iter idx: %d\n", iter->index);
+ dprintf("iter lba: %"PRIu64"\n", iter->start_lba);
if (opt.hand)
- printf("hand lba: %u\n",
+ dprintf("hand lba: %u\n",
((struct disk_dos_part_entry *)hdat.data)->start_lba);
#endif
if (ndata && !opt.brkchain) /* boot only if we actually chainload */
do_boot(data, ndata);
else
- error("Service-only run completed, exiting.\n");
+ puts("Service-only run completed, exiting.");
bail:
pi_del(&iter);
/* Free allocated areas */
sdi = syslinux_derivative_info();
if (sdi->c.filesystem != SYSLINUX_FS_ISOLINUX) {
- error ("The isolinux= option is only valid when run from ISOLINUX.\n");
+ error("The isolinux= option is only valid when run from ISOLINUX.");
goto bail;
}
file_lba = get_file_lba(opt.file);
if (file_lba == 0) {
- error("Failed to find LBA offset of the boot file\n");
+ error("Failed to find LBA offset of the boot file.");
goto bail;
}
/* Set it */
return 0;
if (data->size < sizeof(struct grub_stage2_patch_area)) {
- error("The file specified by grub=<loader> is too small to be stage2 of GRUB Legacy.\n");
+ error("The file specified by grub=<loader> is too small to be stage2 of GRUB Legacy.");
goto bail;
}
stage2 = data->data;
*/
if (stage2->compat_version_major != 3
|| stage2->compat_version_minor != 2) {
- error("The file specified by grub=<loader> is not a supported stage2 GRUB Legacy binary.\n");
+ error("The file specified by grub=<loader> is not a supported stage2 GRUB Legacy binary.");
goto bail;
}
*/
if (opt.grubcfg) {
if (strlen(opt.grubcfg) > sizeof(stage2->config_file) - 1) {
- error ("The config filename length can't exceed 88 characters.\n");
+ error("The config filename length can't exceed 88 characters.");
goto bail;
}
dprintf(" fs_lba offset is %d\n", fs_lba);
/* DRMK only uses a DWORD */
if (fs_lba > 0xffffffff) {
- error("LBA very large; Only using lower 32 bits; DRMK will probably fail\n");
+ error("LBA very large; Only using lower 32 bits; DRMK will probably fail.");
}
opt.regs.ss = opt.regs.fs = opt.regs.gs = 0; /* Used before initialized */
if (!realloc(data->data, tsize)) {
- error("Failed to realloc for DRMK.\n");
+ error("Failed to realloc for DRMK.");
goto bail;
}
data->size = tsize;
type2 = bpb_detect(sec->data, "bss/sect");
if (!type1 || !type2) {
- error("Couldn't determine the BPB type for option 'bss'.\n");
+ error("Couldn't determine the BPB type for option 'bss'.");
goto bail;
}
if (type1 != type2) {
error("Option 'bss' can't be used,\n"
- "when a sector and a file have incompatible BPBs.\n");
+ "when a sector and a file have incompatible BPBs.");
goto bail;
}
if (memcmp(org, data->data, data->size)) {
if (disk_write_sectors(&iter->di, iter->start_lba, data->data, 1)) {
- error("Cannot write the updated sector.\n");
+ error("Cannot write the updated sector.");
goto bail;
}
/* function can be called again */
return 0;
if (miter->type != typedos) {
- error("Option '[un]hide[all]' is meaningful only for legacy (DOS) partition scheme.\n");
+ error("Option '[un]hide[all]' works only for legacy (DOS) partition scheme.");
return -1;
}
if (miter->index > 4 && !(opt.hide & HIDE_EXT))
- error("WARNING: your partition is logical, so it can't be unhidden without 'unhideall'.\n");
+ warn("Specified partition is logical, so it can't be unhidden without 'unhideall'.");
if (!(iter = pi_begin(&miter->di, PIF_STEPALL)))
return -1;
werr |= disk_write_sectors(&iter->di, iter->dos.cebr_lba, iter->data, 1);
}
if (werr)
- error("WARNING: failed to write E/MBR during '[un]hide[all]'\n");
+ warn("Failed to write E/MBR during '[un]hide[all]'.");
bail:
pi_del(&iter);
return 0;
if (miter->type != typedos) {
- error("Option 'fixchs' is meaningful only for legacy (DOS) partition scheme.\n");
+ error("Option 'fixchs' works only for legacy (DOS) partition scheme.");
return -1;
}
werr |= disk_write_sectors(&iter->di, iter->dos.cebr_lba, iter->data, 1);
}
if (werr)
- error("WARNING: failed to write E/MBR during 'fixchs'\n");
+ warn("Failed to write E/MBR during 'fixchs'.");
bail:
pi_del(&iter);
val = (segval << 4) + offval;
if (val < ADDRMIN || val > ADDRMAX) {
- error("Invalid seg:off:* address specified..\n");
+ error("Invalid seg:off:* address specified.");
goto bail;
}
val = (segval << 4) + ipval;
if (ipval > 0xFFFE || val < ADDRMIN || val > ADDRMAX) {
- error("Invalid seg:*:ip address specified.\n");
+ error("Invalid seg:*:ip address specified.");
goto bail;
}
static void usage(void)
{
- unsigned int i;
- static const char key[] = "Press any key...\n";
+ size_t i;
static const char *const usage[] = {
-"\
-Usage:\n\
- chain.c32 [options]\n\
- chain.c32 {fd|hd}<disk#>{,| }[<part#>] [options]\n\
- chain.c32 mbr{:|=}<id>{,| }[<part#>] [options]\n\
- chain.c32 guid{:|=}<guid>{,| }[<part#>] [options]\n\
- chain.c32 label{:|=}<label> [<part#>] [options]\n\
- chain.c32 boot{,| }[<part#>] [options]\n\
- chain.c32 fs [options]\n\
-", "\
-\nOptions ('no' prefix specifies default value):\n\
- sect[=<s[:o[:i]]>] Load sector at <s:o>, jump to <s:i>\n\
- - defaults to 0:0x7C00:0x7C00\n\
- - ommited o/i values default to 0\n\
- maps Map loaded sector into real memory\n\
- nosetbpb Fix BPB fields in loaded sector\n\
- nofilebpb Apply 'setbpb' to loaded file\n\
- nosave Write adjusted sector back to disk\n\
- hand Prepare handover area\n\
- nohptr Force ds:si and ds:bp to point to handover area\n\
- noswap Swap drive numbers, if bootdisk is not fd0/hd0\n\
- nohide Disable all hide variations (also the default)\n\
- hide Hide primary partitions, unhide selected partition\n\
- hideall Hide *all* partitions, unhide selected partition\n\
- unhide Unhide primary partitions\n\
- unhideall Unhide *all* partitions\n\
- nofixchs Walk *all* partitions and fix E/MBRs' chs values\n\
- nokeeppxe Keep the PXE and UNDI stacks in memory (PXELINUX)\n\
- nowarn Wait for a keypress to continue chainloading\n\
- - useful to see emited warnings\n\
- nobreak Actually perform the chainloading\n\
-", "\
-\nOptions continued ...\n\
- file=<file> Load and execute <file>\n\
- seg=<s[:o[:i]]> Load file at <s:o>, jump to <s:i>\n\
- - defaults to 0:0x7C00:0x7C00\n\
- - ommited o/i values default to 0\n\
- isolinux=<loader> Load another version of ISOLINUX\n\
- ntldr=<loader> Load Windows NTLDR, SETUPLDR.BIN or BOOTMGR\n\
- reactos=<loader> Load ReactOS's loader\n\
- cmldr=<loader> Load Recovery Console of Windows NT/2K/XP/2003\n\
- freedos=<loader> Load FreeDOS KERNEL.SYS\n\
- msdos=<loader> Load MS-DOS 2.xx - 6.xx IO.SYS\n\
- msdos7=<loader> Load MS-DOS 7+ IO.SYS\n\
- pcdos=<loader> Load PC-DOS IBMBIO.COM\n\
- drmk=<loader> Load DRMK DELLBIO.BIN\n\
- grub=<loader> Load GRUB Legacy stage2\n\
- grubcfg=<filename> Set alternative config filename for GRUB Legacy\n\
- grldr=<loader> Load GRUB4DOS grldr\n\
- bss=<filename> Emulate syslinux's BSS\n\
- bs=<filename> Emulate syslinux's BS\n\
-\nPlease see doc/chain.txt for the detailed documentation.\n\
-"
- };
+"Usage:",
+"",
+" disk + partition selection:",
+" chain.c32 [options]",
+" chain.c32 hd#[,#] [options]",
+" chain.c32 fd#[,#] [options]",
+" chain.c32 mbr=<id>[,#] [options]",
+" chain.c32 guid=<guid>[,#] [options]",
+" chain.c32 boot[,#] [options]",
+"",
+" direct partition selection:",
+" chain.c32 guid=<guid> [options]",
+" chain.c32 label=<label> [options]",
+" chain.c32 fs [options]",
+"",
+"You can use ':' instead of '=' and ' ' instead of ','.",
+"The default is 'boot,0'.",
+"",
+"Options:",
+" sect[=<s[:o[:i]]>] Load sector at <s:o>, jump to <s:i>",
+" - defaults to 0:0x7C00:0x7C00",
+" - omitted o/i values default to 0",
+" maps Map loaded sector into real memory",
+" setbpb Fix BPB fields in loaded sector",
+" filebpb Apply 'setbpb' to loaded file",
+" save Write adjusted sector back to disk",
+" hand Prepare handover area",
+" hptr Force ds:si and ds:bp to point to handover area",
+" swap Swap drive numbers, if bootdisk is not fd0/hd0",
+" nohide Disable all hide variations (default)",
+" hide Hide primary partitions, unhide selected partition",
+" hideall Hide *all* partitions, unhide selected partition",
+" unhide Unhide primary partitions",
+" unhideall Unhide *all* partitions",
+" fixchs Walk *all* partitions and fix E/MBRs' CHS values",
+" keeppxe Keep the PXE and UNDI stacks in memory (PXELINUX)",
+" warn Wait for a keypress to continue chainloading",
+" break Don't chainload",
+"",
+" file=<file> Load and execute <file>",
+" seg=<s[:o[:i]]> Load file at <s:o>, jump to <s:i>",
+" - defaults to 0:0x7C00:0x7C00",
+" - omitted o/i values default to 0",
+" isolinux=<loader> Load another version of ISOLINUX",
+" ntldr=<loader> Load Windows NTLDR, SETUPLDR.BIN or BOOTMGR",
+" reactos=<loader> Load ReactOS's loader",
+" cmldr=<loader> Load Recovery Console of Windows NT/2K/XP/2003",
+" freedos=<loader> Load FreeDOS KERNEL.SYS",
+" msdos=<loader> Load MS-DOS 2.xx - 6.xx IO.SYS",
+" msdos7=<loader> Load MS-DOS 7+ IO.SYS",
+" pcdos=<loader> Load PC-DOS IBMBIO.COM",
+" drmk=<loader> Load DRMK DELLBIO.BIN",
+" grub=<loader> Load GRUB Legacy stage2",
+" grubcfg=<config> Set alternative config filename for GRUB Legacy",
+" grldr=<loader> Load GRUB4DOS grldr",
+" bss=<sectimage> Emulate syslinux's BSS",
+" bs=<sectimage> Emulate syslinux's BS",
+"",
+"Please see doc/chain.txt for the detailed documentation."
+};
for (i = 0; i < sizeof(usage)/sizeof(usage[0]); i++) {
- if (i) {
- error(key);
+ if (i % 20 == 19) {
+ puts("Press any key...");
wait_key();
}
- error(usage[i]);
+ puts(usage[i]);
}
}
}
if (opt.grubcfg && !opt.grub) {
- error("grubcfg=<filename> must be used together with grub=<loader>.\n");
+ error("grubcfg=<filename> must be used together with grub=<loader>.");
goto bail;
}
if (opt.filebpb && !opt.file) {
- error("Option 'filebpb' requires a file.\n");
+ error("Option 'filebpb' requires a file.");
goto bail;
}
if (opt.save && !opt.sect) {
- error("Option 'save' requires a sector.\n");
+ error("Option 'save' requires a sector.");
goto bail;
}
if (opt.setbpb && !opt.sect) {
- error("Option 'setbpb' requires a sector.\n");
+ error("Option 'setbpb' requires a sector.");
goto bail;
}
if (opt.maps && !opt.sect) {
- error("Option 'maps' requires a sector.\n");
+ error("Option 'maps' requires a sector.");
goto bail;
}
if (pi_ctor(iter, di, flags))
return -1;
- if (!(iter->data = malloc(sizeof(struct disk_dos_mbr))))
+ if (!(iter->data = malloc(sizeof(struct disk_dos_mbr)))) {
+ critm();
goto bail;
+ }
memcpy(iter->data, mbr, sizeof(struct disk_dos_mbr));
siz = (uint64_t)gpth->part_count * gpth->part_size;
- if (!(iter->data = malloc((size_t)siz)))
+ if (!(iter->data = malloc((size_t)siz))) {
+ critm();
goto bail;
+ }
memcpy(iter->data, gptl, (size_t)siz);
return 0;
if (ost_is_ext(dp[0].ostype)) {
- error("1st EBR entry must be data or empty.\n");
+ error("The 1st EBR entry must be data or empty.");
return -1;
}
!sane(dp[0].start_lba, dp[0].length) ||
end_log > iter->dos.nebr_siz) {
- error("Logical partition (in EBR) with invalid offset and/or length.\n");
+ error("Logical partition (in EBR) with invalid offset and/or length.");
return -1;
}
return 0;
if (!ost_is_nondata(dp[1].ostype)) {
- error("The 2nd EBR entry must be extended or empty.\n");
+ error("The 2nd EBR entry must be extended or empty.");
return -1;
}
!sane(dp[1].start_lba, dp[1].length) ||
end_ebr > iter->dos.bebr_siz) {
- error("Extended partition (EBR) with invalid offset and/or length.\n");
+ error("Extended partition (EBR) with invalid offset and/or length.");
return -1;
}
!dp->length ||
!sane(dp->start_lba, dp->length) ||
dp->start_lba + dp->length > iter->di.lbacnt) {
- error("Primary partition (in MBR) with invalid offset and/or length.\n");
+ error("Primary partition (in MBR) with invalid offset and/or length.");
return -1;
}
if (gp->lba_first < iter->gpt.ufirst ||
gp->lba_last > iter->gpt.ulast) {
- error("LBA sectors of GPT partition are beyond the range allowed in GPT header.\n");
+ error("LBA sectors of GPT partition are beyond the range allowed in GPT header.");
return -1;
}
if (ost_is_ext(dp->ostype)) {
if (iter->dos.bebr_index0 >= 0) {
- error("More than 1 extended partition.\n");
+ error("More than 1 extended partition.");
iter->status = PI_INSANE;
return -1;
}
free(iter->data);
if (!(iter->data =
disk_read_sectors(&iter->di, iter->dos.nebr_lba, 1))) {
- error("Couldn't load EBR.\n");
+ error("Couldn't load EBR.");
iter->status = PI_ERRLOAD;
return -1;
}
hold_crc32 = gh->chksum;
gh->chksum = 0;
if (!valid_crc(hold_crc32, (const uint8_t *)gh, gh->hdr_size)) {
- error("WARNING: Primary GPT header checksum invalid.\n");
+ warn("Primary GPT header checksum invalid.");
/* retry with backup */
lba_alt = gh->lba_alt;
free(gh);
if (!(gh = *_gh = disk_read_sectors(diskinfo, lba_alt, 1))) {
- error("Couldn't read backup GPT header.\n");
+ error("Couldn't read backup GPT header.");
return -1;
}
hold_crc32 = gh->chksum;
gh->chksum = 0;
if (!valid_crc(hold_crc32, (const uint8_t *)gh, gh->hdr_size)) {
- error("Secondary GPT header checksum invalid.\n");
+ error("Secondary GPT header checksum invalid.");
return -1;
}
}
{
struct part_iter *iter;
if (!(iter = malloc(sizeof(struct part_iter))))
- error("Couldn't allocate memory for the iterator.\n");
+ critm();
else
memset(iter, 0, sizeof(struct part_iter));
return iter;
/* Read MBR */
if (!(mbr = disk_read_sectors(di, 0, 1))) {
- error("Couldn't read first disk sector.\n");
+ error("Couldn't read the first disk sector.");
goto bail;
}
/* Check for MBR magic */
if (mbr->sig != disk_mbr_sig_magic) {
- error("WARNING: no MBR magic, treating disk as raw.\n");
+ warn("No MBR magic, treating disk as raw.");
/* looks like RAW */
ret = pi_ctor(iter, di, flags);
goto bail;
/* Check for GPT protective MBR */
if (mbr->table[0].ostype == 0xEE) {
if (!(gpth = disk_read_sectors(di, 1, 1))) {
- error("Couldn't read potential GPT header.\n");
+ error("Couldn't read potential GPT header.");
goto bail;
}
}
uint64_t gpt_lsiz; /* size of GPT partition list in bytes */
uint64_t gpt_lcnt; /* size of GPT partition in sectors */
#ifdef DEBUG
- puts("Looks like a GPT v1.0 disk.");
+ dprintf("Looks like a GPT v1.0 disk.\n");
disk_gpt_header_dump(gpth);
#endif
/* Verify checksum, fallback to backup, then bail if invalid */
gpth->lba_last_usable + gpt_lcnt >= gpth->lba_alt ||
gpth->lba_alt >= di->lbacnt ||
gpth->part_size < sizeof(struct disk_gpt_part_entry)) {
- error("Invalid GPT header's values.\n");
+ error("Invalid GPT header's values.");
goto bail;
}
if (!(gptl = disk_read_sectors(di, gpt_loff, gpt_lcnt))) {
- error("Couldn't read GPT partition list.\n");
+ error("Couldn't read GPT partition list.");
goto bail;
}
/* Check array checksum(s). */
if (!valid_crc(gpth->table_chksum, (const uint8_t *)gptl, (unsigned int)gpt_lsiz)) {
- error("Checksum of the main GPT partition list is invalid, trying backup.\n");
+ warn("Checksum of the main GPT partition list is invalid, trying backup.");
free(gptl);
/* secondary array directly precedes secondary header */
if (!(gptl = disk_read_sectors(di, gpth->lba_alt - gpt_lcnt, gpt_lcnt))) {
- error("Couldn't read backup GPT partition list.\n");
+ error("Couldn't read backup GPT partition list.");
goto bail;
}
if (!valid_crc(gpth->table_chksum, (const uint8_t *)gptl, gpt_lsiz)) {
- error("Checksum of the backup GPT partition list is invalid, giving up.\n");
+ error("Checksum of the backup GPT partition list is invalid, giving up.");
goto bail;
}
}
int bpb_detect(const uint8_t *bpb, const char *tag);
int guid_is0(const struct guid *guid);
-static inline
-void error(const char *msg)
+static inline int warn(const char *x)
{
- fputs(msg, stderr);
+ return fprintf(stderr, "WARN: %s\n", x);
}
+static inline int error(const char *x)
+{
+ return fprintf(stderr, "ERR: %s\n", x);
+}
+
+static inline int crit(const char *x)
+{
+ return fprintf(stderr, "CRIT: %s @%s:%d\n", x, __FILE__, __LINE__);
+}
+
+#define critm() crit("Malloc failure.")
+
#endif
/* vim: set ts=8 sts=4 sw=4 noet: */
chain [drive/partition] [options]
+In case of repeated arguments, rightmost ones take precedence.
+
+
DRIVE / PARTITION SPECIFICATION
Drive can be specified as 'hd#', 'fd#', 'boot', 'mbr', or 'guid'.
-- 'mbr' will select a drive by a signature.
-- 'guid' will select a drive by a guid
+- 'mbr' will select a drive by its signature.
+- 'guid' will select a drive by its guid (GPT only).
- 'boot' is the drive syslinux was booted from. This is the default value, if
nothing else is specified.
- 'hd#' and 'fd#' are standard ways to specify drive number as seen by bios,
starting from 0.
-Option 'guid' is shared with partition selection (see below). If you happened
+Option 'guid' is shared with partition selection (see below). If you happen
to have non-unique guids, they are searched in disk0, partitions of disk0,
disk1 ... order.
-The priority of those options are the same as in the above list.
-
-If you specify the same value more than once, the last value will be used.
-
'mbr' and 'guid' take extra parameter - you should use ':' or '=' as a
delimiter.
-
Partition can be specified as '#', 'guid', 'label' or 'fs'.
- 'guid' option will select a partition by a guid (not a type guid !)
- '#' is the standard method. Partitions 1-4 are primary, 5+ logical, 0 = boot
MBR (default).
-The priority of those options are the same as in the above list.
-
If you use a number to select a partition it should be specified after a drive
using space or comma as delimiters (after 'hd#', 'fd#', 'mbr', 'guid' or 'boot').
+
OPTIONS
file=<file>
*nofile
other bootloader or kernel, it's almost always mandatory.
The defaults, if option is not specified, are 0:0x7c00:0x7c00
-If any of the fields are ommited (e.g. 0x2000::), they default to 0.
+If any of the fields are omitted (e.g. 0x2000::), they default to 0.
sect=<segment>:<offset>:<ip>
nosect
is being chainloaded, sector is not necessary.
The defaults if option is not specified, are 0:0x7c00:0x7c00.
-If some of the fields are ommited (e.g. 0x2000::), they default to 0.
+If some of the fields are omitted (e.g. 0x2000::), they default to 0.
*maps
nomaps