📄 boot.c
字号:
dev = S_ISREG(st.st_mode) ? st.st_dev : st.st_rdev; if ( (mask = has_partitions(dev)) ) { k = dev & ~mask; k = !table ? 1 : k>=1 && k<=4; if (k) { dev_open(&d, dev&mask, O_BYPASS); /* bypass any open */ npart = stralloc(d.name); dev_close(&d); } } #endif if (verbose>=3) { printf("Name: %s yields MBR: %s (with%s primary partition check)\n", boot, k ? npart : "(NULL)", table ? "" : "out"); } if (k) return npart; else return NULL;}#define PART(s,n) (((struct partition *) (s)[0].par_c.ptable)[(n)])void boot_other(char *loader,char *boot,char *part,IMAGE_DESCR *descr){ int b_fd,p_fd,walk,found,size;#ifdef LCF_BUILTIN BUILTIN_FILE *chain; char *cname;#else int l_fd;#endif unsigned short magic;#ifdef BIG_CHAIN BOOT_SECTOR buff[BIG_CHAIN]; BOOT_SECTOR zbuff; int mapped;#else BOOT_SECTOR buff[SETUPSECS-1];#endif struct stat st; char *pos; int i, code; int letter = 0; int unsafe; if (!loader) loader = DFL_CHAIN;#ifdef LCF_BUILTIN#ifndef LCF_SOLO_CHAIN if (strstr(loader,"os2")) { chain = &Os2_d; cname = "OS/2"; } else#endif { chain = &Chain; cname = "CHAIN"; }#endif if (part && strlen(part)>0 && strlen(part)<=2) { if (part[1]==0 || part[1]==':') { letter = toupper(part[0]); if (letter>='C' && letter<='Z') { letter += 0x80-'C'; part = NULL; } else letter = 0; } } unsafe = cfg_get_flag(cf_other, "unsafe"); if (!part && !unsafe) part = boot_mbr(boot, 1); /* part may still be NULL */ if (verbose > 0) {#ifdef LCF_BUILTIN printf("Boot other: %s%s%s, loader %s\n", boot, part ? ", on " : "", part ? part : "", cname);#else printf("Boot other: %s%s%s, loader %s", boot, part ? ", on " : "", part ? part : "", loader); show_link(loader); printf("\n");#endif }#ifdef LCF_AUTOAUTO if (!cfg_get_flag(cf_other, "change")) { autoauto = 1; /* flag that change rules may be automatically inserted */ do_cr_auto(); autoauto = 0; }#endif if (unsafe) { (void) geo_open_boot(&geo,boot); if (part) die("TABLE and UNSAFE are mutually incompatible."); } else { b_fd = geo_open(&geo,boot,O_RDONLY); if (fstat(b_fd,&st) < 0) die("fstat %s: %s",boot,strerror(errno)); if (!geo.file) part_verify(st.st_rdev,0); else if (st.st_size > SECTOR_SIZE && !nowarn) { fprintf(errstd,"Warning: 'other = %s' specifies a file that is longer\n" " than a single sector.", boot); if (st.st_size >= SECTOR_SIZE*(SETUPSECS-1) && read(b_fd, buff[0].sector, SECTOR_SIZE*(SETUPSECS-1)) == SECTOR_SIZE*(SETUPSECS-1) && !strncmp((char*)buff[2].sector+2,"HdrS",4) ) { fprintf(errstd," This file may actually be an 'image ='"); } fprintf(errstd, "\n"); } if (lseek(b_fd,(int) BOOT_SIG_OFFSET,SEEK_SET) < 0) die("lseek %s: %s",boot,strerror(errno)); if ((size = read(b_fd, (char *)&magic, 2)) != 2) { if (size < 0) die("read %s: %s",boot,strerror(errno)); else die("Can't get magic number of %s",boot); } if (magic != BOOT_SIGNATURE) die("First sector of %s doesn't have a valid boot signature",boot); }/* process the 'master-boot' or 'boot-as' options */ i = cfg_get_flag(cf_other,"master-boot"); pos = cfg_get_strg(cf_other,"boot-as"); if (i && pos) die("'master-boot' and 'boot-as' are mutually exclusive 'other=' options"); if (!i && !pos) { i = cfg_get_flag(cf_options,"master-boot"); pos = cfg_get_strg(cf_options,"boot-as"); if (i && pos) die("'master-boot' and 'boot-as' are mutually exclusive global options"); } if (i) code = -1; /* master-boot in use */ else if (pos) { code = to_number(pos); if (code >= 80 && code <= 89) { /* convert to 0x80 to 0x89 */ fprintf(errstd,"Warning: Radix error, 'boot-as=%d' taken to mean 'boot-as=0x%x'\n", code, code+0x30); code += 0x30; } if ( !((code>=0 && code<=3) || (code>=0x80 && code<=DEV_MASK)) ) die("Illegal BIOS device code specified in 'boot-as=0x%02x'", code); } else code = -2; if (code != -2) { curr_drv_map += 2; /* add 2 spaces */ if (curr_drv_map >= DRVMAP_SIZE) cfg_error("Too many drive mappings (more than %d)",DRVMAP_SIZE); if (verbose > 1) { char *s, n[8]; if (code==-1) s = "0/0x80"; else sprintf((s=n),"0x%02x", code); printf(" Swapping BIOS boot drive with %s, as needed\n", s); } for (i=curr_drv_map-1; i>1; i--) drv_map[i] = drv_map[i-2]; drv_map[0] = 0xFFFF; /* reserve 2 slots */ drv_map[1] = code<<8 | 0xFF; } memset(buff,0,sizeof(buff));#ifdef BIG_CHAIN zbuff = buff[0]; /* zero out zbuff */#endif#ifndef LCF_BUILTIN if ((l_fd = open(loader,O_RDONLY)) < 0) die("open %s: %s",loader,strerror(errno)); if ((size = read(l_fd,buff,sizeof(buff)+1)) < 0) die("read %s: %s",loader,strerror(errno)); if (size > sizeof(buff)) die("Chain loader %s is too big",loader); check_version(buff,STAGE_CHAIN);#else size = chain->size; if (size > sizeof(buff)) die("Chain loader %s is too big",loader); memcpy(buff, chain->data, size);#endif if (!part) { p_fd = -1; /* pacify GCC */ PART(buff,0).boot_ind = geo.device; PART(buff,0).start_sect = geo.start; /* pseudo partition table */ if (verbose > 0) printf("Pseudo partition start: %d\n", geo.start); } else { if ((p_fd = open(part,O_RDONLY)) < 0) die("open %s: %s",part,strerror(errno)); if (lseek(p_fd,(int) PART_TABLE_OFFSET,SEEK_SET) < 0) die("lseek %s: %s",part,strerror(errno)); if (read(p_fd,(char *) buff[0].par_c.ptable,PART_TABLE_SIZE) != PART_TABLE_SIZE) die("read %s: %s",part,strerror(errno)); found = 0; for (walk = 0; walk < PARTITION_ENTRIES; walk++) if (!PART(buff,walk).sys_ind || PART(buff,walk).start_sect != geo.start) { /* * Don't remember what this is supposed to be good for :-( */ if (PART(buff,walk).sys_ind != PART_DOS12 && PART(buff,walk). sys_ind != PART_DOS16_SMALL && PART(buff,walk).sys_ind != PART_DOS16_BIG) PART(buff,walk).sys_ind = PART_INVALID; } else { if (found) die("Duplicate entry in partition table"); buff[0].par_c.offset = walk*PARTITION_ENTRY; PART(buff,walk).boot_ind = 0x80; found = 1; } if (!found) die("Partition entry not found."); (void) close(p_fd); }#ifndef LCF_BUILTIN (void) close(l_fd);#endif buff[0].par_c.drive = geo.device; buff[0].par_c.head = letter ? letter : geo.device; /* IBM boot manager passes drive letter in offset 0x25 */ if (verbose>=5) printf("boot_other: drive=0x%02x logical=0x%02x\n", buff[0].par_c.drive, buff[0].par_c.head); drv_map[curr_drv_map] = 0; prt_map[curr_prt_map] = 0; pos = (char *) buff+buff[0].par_c.drvmap; memcpy(pos,drv_map,sizeof(drv_map)); memcpy(pos+sizeof(drv_map),prt_map,sizeof(prt_map)-2); size = (size + SECTOR_SIZE - 1) / SECTOR_SIZE;#ifndef BIG_CHAIN map_add_zero();#else if (size > SETUPSECS-1) { zbuff.sector[VSS_NUM] = mapped = size+1; map_add_sector(zbuff.sector); } else { map_add_zero(); mapped = SETUPSECS; }#endif for (i = 0; i < size; i++) map_add_sector(&buff[i]); for (i = size; i < SETUPSECS-1; i++) map_add_zero(); map_add(&geo,0,1);#ifndef BIG_CHAIN (void) map_end_section(&descr->start,SETUPSECS+SPECIAL_SECTORS); /* size is known */ geo_close(&geo); if (verbose > 1) printf("Mapped %d (%d+1+1) sectors.\n", SETUPSECS+SPECIAL_SECTORS, SETUPSECS);#else (void) map_end_section(&descr->start, mapped+SPECIAL_SECTORS+SPECIAL_BOOTSECT); /* size is known */ geo_close(&geo); if (verbose > 1) printf("Mapped %d (%d+1+1) sectors.\n", mapped+SPECIAL_SECTORS, mapped);#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -