📄 lilo.c
字号:
/* lilo.c - LILO command-line parameter processing *//*Copyright 1992-1998 Werner Almesberger.Copyright 1999-2002 John Coffman.All rights reserved.Licensed under the terms contained in the file 'COPYING' in the source directory.*/#include <stdlib.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <fcntl.h>#include <errno.h>#include <sys/stat.h>#include <asm/page.h>#include "config.h"#include "common.h"#include "lilo.h"#include "boot.h"#include "temp.h"#include "device.h"#include "geometry.h"#include "map.h"#include "bsect.h"#include "cfg.h"#include "identify.h"#include "partition.h"#include "probe.h"#include "md-int.h"#include "edit.h"#include "flags.i"static int lowest;static md_array_info_t md_array_info;static DT_ENTRY *md_disk;static DT_ENTRY *disk;static unsigned long raid_base, raid_offset[MAX_RAID];static char *raid_mbr[MAX_RAID];static int raid_device[MAX_RAID+1];static int raid_bios[MAX_RAID+1];static int device, md_bios;enum {MD_NULL=0, MD_PARALLEL, MD_MIXED, MD_SKEWED};int do_md_install;char *config_file; /* actual name of the config file */int config_read; /* readable by other than root */FILE *errstd;static char *raid_list[MAX_RAID];static int list_index[MAX_RAID];static int ndisk, nlist, faulty;#define IS_COVERED 0x1000#define TO_BE_COVERED 0x2000#define COVERED (IS_COVERED|TO_BE_COVERED)static int is_primary(int device){ int mask; mask = has_partitions(device); if (!mask) die("is_primary: Not a valid device 0x%04X", device); mask = device & ~mask; return (mask && mask<=PART_MAX);}#if 0static int is_master(int device){ int mask; mask = has_partitions(device); if (!mask) die("is_master: Not a valid device 0x%04X", device); mask = device & ~mask; return (!mask);}#endifstatic int master(int device){ int mask; mask = has_partitions(device); if (!mask) die("master: Not a valid device 0x%04X", device); return device & mask;}static int is_accessible(int device){ int mask; mask = has_partitions(device); if (!mask) die("is_accessible: Not a valid device 0x%04X", device); mask = device & ~mask; return (mask<=PART_MAX);}static void raid_final(void){ int pass, force; char *cp; if (verbose>=2) printf("do_md_install: %s\n", do_md_install == MD_PARALLEL ? "MD_PARALLEL" : do_md_install == MD_MIXED ? "MD_MIXED" : do_md_install == MD_SKEWED ? "MD_SKEWED" : "unknown"); if (extra == X_MBR_ONLY) { pass = 0; while (pass < ndisk) { if (!test) { force = 0; /* we need to re-visit the logic about backups */ if ((cp=cfg_get_strg(cf_options,"force-backup"))) force=1; else cp=cfg_get_strg(cf_options,"backup"); bsect_raid_update(raid_mbr[pass], raid_offset[pass], cp, force, pass); if (!nowarn) fprintf(errstd, "The Master boot record of %s has been updated.\n", raid_mbr[pass]); } else { if (pass==0) { bsect_cancel(); if (passw) fprintf(errstd,"The password crc file has *NOT* been updated.\n"); fprintf(errstd, "The map file has *NOT* been altered.\n"); } fprintf(errstd,"The Master boot record of %s has *NOT* been altered.\n", raid_mbr[pass]); } pass++; } } else { /* extra != X_MBR_ONLY */ char *boot = cfg_get_strg(cf_options,"boot"); raid_flags &= ~FLAG_RAID_DEFEAT; /* change won't affect /dev/mdX */ if (!test) { force = 0; if ((cp=cfg_get_strg(cf_options,"force-backup"))) force=1; else cp=cfg_get_strg(cf_options,"backup"); /* write out the /dev/mdX boot records */ bsect_raid_update(boot, 0L, cp, force, 0); if (!nowarn) fprintf(errstd, "The boot record of %s has been updated.\n", boot); } else { bsect_cancel(); if (passw) fprintf(errstd,"The password crc file has *NOT* been updated.\n"); fprintf(errstd, "The map file has *NOT* been updated.\n"); fprintf(errstd,"The boot record of %s has *NOT* been updated.\n", boot); } if (extra == X_NONE || (extra == X_AUTO && do_md_install == MD_PARALLEL) ) return; if (extra == X_SPEC) for (pass = 0; pass < nlist; pass++) { int index; if (raid_bios[list_index[pass]] & 0xFF) { index = list_index[pass]; /* within RAID set */ } else { /* not in the RAID set */ raid_flags |= FLAG_RAID_DEFEAT; /* make outsider invisible */ index = lowest; } if (verbose>=2) printf("Specifed partition: %s raid offset = %08lX\n", raid_list[pass], raid_offset[index]); if (!test) { bsect_raid_update(raid_list[pass], raid_offset[index], NULL, 0, 1); } if (test || !nowarn) fprintf(errstd,"The boot record of %s has%s been updated.\n", raid_list[pass], (test ? " *NOT*" : "")); raid_flags &= ~FLAG_RAID_DEFEAT; /* restore DEFEAT flag to 0 */ } else { /* extra = X_AUTO */ for (pass = 0; pass < ndisk; pass++) if (!(raid_bios[pass] & IS_COVERED) && (raid_bios[pass] & 0xFF) != 0x80) { if (!test) bsect_raid_update(raid_mbr[pass], raid_offset[pass], NULL, 0, 1); if (test || !nowarn) fprintf(errstd,"The Master boot record of %s has%s been updated.\n", raid_mbr[pass], (test ? " *NOT*" : "")); } } } if (raid_flags & FLAG_RAID_NOWRITE) { if (!nowarn) { fprintf(errstd, "Warning: FLAG_RAID_NOWRITE has been set.\n"); if (verbose >= 1) fprintf(errstd, " The boot loader will be unable to update the stored command line;\n" " 'lock' and 'fallback' are not operable; the 'lilo -R' boot command\n" " line will be locked.\n\n"); } }}static long raid_setup(void){ int pass, mask; struct stat st; int md_fd; md_disk_info_t md_disk_info; GEOMETRY geo; char *boot, *extrap; int ro_set, all_pri_eq, pri_index; long pri_offset; int raid_limit; if ((boot=cfg_get_strg(cf_options,"boot")) != NULL && strncmp("/dev/md",boot,7) == 0) { if ((md_fd=open(boot,O_NOACCESS)) < 0) die("Unable to open %s",boot); if (fstat(md_fd,&st) < 0) die("Unable to stat %s",boot); if (!S_ISBLK(st.st_mode)) die("%s is not a block device",boot); if (ioctl(md_fd,GET_ARRAY_INFO,&md_array_info) < 0) die("Unable to get RAID info on %s",boot); if ((md_array_info.major_version == 0) && (md_array_info.minor_version < 90)) die("Raid versions < 0.90 are not supported"); if (md_array_info.level != 1) die("Only RAID1 devices are supported as boot devices"); if (!linear && !lba32) {#if 0 cfg_set(cf_options,"lba32",NULL,NULL);#endif lba32 = 1; if (!nowarn) fprintf(errstd,"Warning: RAID install requires LBA32 or LINEAR;" " LBA32 assumed.\n"); } extrap = cfg_get_strg(cf_options, RAID_EXTRA_BOOT); extra = !extrap ? X_AUTO : !strcasecmp(extrap,"none") ? X_NONE : !strcasecmp(extrap,"auto") ? X_AUTO : !strcasecmp(extrap,"mbr-only") ? X_MBR_ONLY : X_SPEC; do_md_install = MD_PARALLEL; all_pri_eq = 1; ro_set = pri_index = pri_offset = 0; raid_flags = FLAG_RAID; md_bios = 0xFF; /* we want to find the minimum */ ndisk = 0; /* count the number of disks on-line */ nlist = 0; faulty = 0; device = (MD_MAJOR << 8) | md_array_info.md_minor; /* search the disk table for a definition */ md_disk = disktab; while (md_disk && md_disk->device != device) md_disk = md_disk->next; if (!md_disk) { md_disk = alloc_t(DT_ENTRY); md_disk->device = (MD_MAJOR << 8) | md_array_info.md_minor; md_disk->bios = -1; /* use the default */ md_disk->next = disktab; disktab = md_disk; } if (verbose >= 2) { printf("RAID info: nr=%d, raid=%d, active=%d, working=%d, failed=%d, spare=%d\n", md_array_info.nr_disks, md_array_info.raid_disks, md_array_info.active_disks, md_array_info.working_disks, md_array_info.failed_disks, md_array_info.spare_disks ); } /* scan through all the RAID devices */ raid_limit = md_array_info.raid_disks + md_array_info.spare_disks; for (pass=0; pass < raid_limit; pass++) { DEVICE dev; int disk_fd; char new_name[MAX_TOKEN+1]; char *np; md_disk_info.number = pass; if (ioctl(md_fd,GET_DISK_INFO,&md_disk_info) < 0) die("main: GET_DISK_INFO: %s", strerror(errno)); device = (md_disk_info.major << 8) | md_disk_info.minor; if(verbose>=2) printf("md: RAIDset device %d = 0x%04X\n", pass, device); if (device == 0) { /* empty slot left over from recovery process */ faulty++; continue; } disk_fd = dev_open(&dev,device,O_NOACCESS); if (md_disk_info.state & (1 << MD_DISK_FAULTY)) { printf("disk %s marked as faulty, skipping\n",dev.name); faulty++; continue; } geo_get(&geo, device, -1, 1); disk = alloc_t(DT_ENTRY); if (verbose>=2) printf("RAID scan: geo_get: returns geo->device = 0x%02X" " for device %04X\n", geo.device, device); disk->bios = geo.device; /* will be overwritten */ disk->device = device; /* used to mask above with 0xFFF0; forces MBR; sloppy, mask may be: 0xFFF8 */ disk->sectors = geo.sectors; disk->heads = geo.heads; disk->cylinders = geo.cylinders; disk->start = geo.start; if (ndisk==0) raid_base = geo.start; raid_offset[ndisk] = geo.start - raid_base; raid_device[ndisk] = device; if (raid_offset[ndisk]) { do_md_install = MD_SKEWED; /* flag non-zero raid_offset */ } if (all_pri_eq && is_primary(device)) { if (ro_set) { all_pri_eq &= (pri_offset == raid_offset[ndisk]); } else { pri_offset = raid_offset[ndisk]; ro_set = 1; pri_index = ndisk; } } if (geo.device < md_bios) { md_bios = geo.device; /* find smallest device code, period */ lowest = ndisk; /* record where */ } raid_bios[ndisk] = geo.device; /* record device code */ disk->next = disktab; disktab = disk; if (verbose >= 2 && do_md_install) { printf("disk->start = %d\t\traid_offset = %ld (%08lX)\n", disk->start, (long)raid_offset[ndisk], (long)raid_offset[ndisk]); } /* derive the MBR name, which may be needed later */ strncpy(new_name,dev.name,MAX_TOKEN); new_name[MAX_TOKEN] = '\0'; np = boot_mbr(dev.name, 0); if (!np) np = stralloc(new_name); raid_mbr[ndisk] = np; if (ndisk==0) { /* use the first disk geometry */ md_disk->sectors = geo.sectors; md_disk->heads = geo.heads; md_disk->cylinders = geo.cylinders; md_disk->start = geo.start; } ndisk++; /* count the disk */ } /* for (pass=... */ if(close(md_fd) < 0) die("Error on close of %s", boot); raid_bios[ndisk] = 0; /* mark the end */ raid_device[ndisk] = 0; all_pri_eq &= ro_set; if (all_pri_eq && do_md_install == MD_SKEWED) { do_md_install = MD_MIXED; } else pri_index = lowest; /* check that all devices have an accessible block for writeback info */ for (pass=0; pass < ndisk; pass++) { if (extra == X_MBR_ONLY) raid_bios[pass] |= TO_BE_COVERED; if (extra == X_AUTO && raid_bios[pass] != 0x80) { if (do_md_install == MD_SKEWED) raid_bios[pass] |= TO_BE_COVERED; if (do_md_install == MD_MIXED) { if (is_primary(raid_device[pass])) raid_bios[pass] |= IS_COVERED; else raid_bios[pass] |= TO_BE_COVERED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -