📄 setboot.cxx
字号:
/* * Copyright (C) 1998, 1999, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <sys/stat.h>#include <sys/ioctl.h>#include <sys/fcntl.h>#include <unistd.h>#include <getopt.h>#include <stdlib.h>#ifndef __FreeBSD__#include <linux/fd.h>#include <linux/hdreg.h>#include <syscall.h>#endif#include <erosimg/App.hxx>/* #include <erosimg/Volume.hxx> */#include <disk/LowVolume.hxx>#include <erosimg/DiskDescrip.hxx>/* #define DEBUG */#ifdef __linux__#ifndef __FreeBSD__#include <linux/fs.h>#include <linux/major.h>#define IS_FLOPPY(st) (MAJOR(st.st_rdev) == FLOPPY_MAJOR)#ifdef SCSI_DISK0_MAJOR#define IS_SCSI_DISK(m) (SCSI_DISK_MAJOR(m))#else#define IS_SCSI_DISK(m) (m == SCSI_DISK_MAJOR)#endif#define IS_HD(st) (MAJOR(st.st_rdev) == IDE0_MAJOR \ || IS_SCSI_DISK(MAJOR(st.st_rdev)) \ || MAJOR(st.st_rdev) == XT_DISK_MAJOR \ || MAJOR(st.st_rdev) == IDE1_MAJOR \ || MAJOR(st.st_rdev) == IDE2_MAJOR \ || MAJOR(st.st_rdev) == IDE3_MAJOR)#endif#endifclass App App("setboot");const char *target;struct Geom { uint32_t hd; uint32_t sec; uint32_t spcyl; uint32_t cyl; uint32_t start;} ;#ifdef __FreeBSD__#include <sys/types.h>#include <sys/disklabel.h>voidGetGeometry(int fd, Geom& geom){ /* Following works for floppies, but something isn't right * about it for hard disks. Not clear what yet. */ struct stat stat; if (0 == fstat(fd, &stat)) { if (S_ISBLK( stat.st_mode)) { struct disklabel disklabel; if (-1 != ioctl(fd, DIOCFGINFO, &disklabel)) { int partition; partition = DISKPART(stat.st_rdev); if (partition < disklabel.d_npartitions) geom.start = disklabel.d_partitions[partition].p_offset; else Diag::fatal(3, "setboot: Unable to obtain disk start\n"); geom.hd = disklabel.d_ntracks; geom.cyl = disklabel.d_ncylinders; geom.sec = disklabel.d_nsectors; geom.spcyl = geom.sec * geom.hd; } else { Diag::fatal(3, "setboot: Unable to obtain disk geometry\n"); } } else { Diag::fatal(1, "setboot: \"%s\" is not a block device\n", target); } } else { Diag::fatal(1, "setboot: Unable to stat \"%s\"\n", target); } return;}#elsevoidGetGeometry(int fd, Geom& geom){ struct floppy_struct fdprm; struct hd_geometry hdprm; struct stat st; fstat(fd, &st); if (S_ISBLK(st.st_mode) == 0) Diag::fatal(1, "setboot: \"%s\" is not a block device\n", target); Diag::printf("Major number for \"%s\" is %d\n", target, MAJOR(st.st_rdev)); if (IS_FLOPPY(st)) { if (ioctl(fd, FDGETPRM, &fdprm) < 0) Diag::fatal(3, "setboot: Unable to obtain floppy geometry\n"); geom.hd = fdprm.head; geom.cyl = fdprm.track; geom.sec = fdprm.sect; geom.start = 0; } else if (IS_HD(st)) { if (ioctl(fd,HDIO_GETGEO,&hdprm) < 0) Diag::fatal(3, "setboot: Unable to obtain hard disk geometry\n"); geom.hd = hdprm.heads; geom.cyl = hdprm.cylinders; geom.sec = hdprm.sectors; geom.start = hdprm.start; } else { Diag::fatal(3, "setboot: \"%s\" has unknown device type\n", target); } geom.spcyl = geom.sec * geom.hd;}#endifstruct BlockTable { uint16_t cylsec; uint8_t head; uint8_t nsec;};voidUpdateBootTable(int fd, Geom& geom, int dowrite){ Geom p; uint32_t start = geom.start; p.start = start; p.spcyl = geom.spcyl; p.sec = geom.sec; p.cyl = start / p.spcyl; start %= p.spcyl; p.hd = start / p.sec; start %= p.sec; p.sec = start + 1; Diag::printf("Geometry c/h/s: %d/%d/%d\n", geom.cyl, geom.hd, geom.sec); Diag::printf("Partition starts at: %d/%d/%d (sector %d)\n", p.cyl, p.hd, p.sec, geom.start); char bootstrap[512]; lseek(fd, SEEK_SET, 0); read(fd, bootstrap, 512); struct BlockTable *btbl = (BlockTable *) &bootstrap[sizeof(VolHdr)+sizeof(uint16_t)]; uint32_t resid = DISK_BOOTSTRAP_SECTORS; uint16_t count = 0; #define MIN(x, y) ((x < y) ? x : y)#define CYLSEC(cyl, sec) ((sec & 0x3fu) | ((cyl << 8)&0xff00u) \ | ((cyl >> 2) & 0xC0u)) for ( ; resid; btbl++, count++) { btbl->nsec = MIN(resid, geom.sec); if (p.sec > 1) /* first one might be short */ btbl->nsec -= (p.sec - 1); btbl->cylsec = CYLSEC(p.cyl, p.sec); btbl->head = p.hd; Diag::printf("c/h/s %d/%d/%d cs=0x%04x nsec=%d\n", p.cyl, p.hd, p.sec, btbl->cylsec, btbl->nsec); p.sec = 1; p.hd++; if (p.hd == geom.hd) { p.cyl++; p.hd = 0; } resid -= btbl->nsec; } * ((uint16_t *) &bootstrap[sizeof(VolHdr)]) = count; if (dowrite) { lseek(fd, SEEK_SET, 0); write(fd, bootstrap, 512); }}voidReadLoadList(int fd){ char bootstrap[512]; lseek(fd, SEEK_SET, 0); read(fd, bootstrap, 512); struct BlockTable *btbl = (BlockTable *) &bootstrap[sizeof(VolHdr)+sizeof(uint16_t)]; uint16_t count = * ((uint16_t *) &bootstrap[sizeof(VolHdr)]);#define SEC(x) (x & 0x3fu)#define CYL(x) ( ((x << 2) & 0x300u) | ((x >> 8) & 0xffu) ) for (uint16_t i = 0; i < count; i++) { Diag::printf("c/h/s %d/%d/%d cs=0x%04x nsec=%d\n", CYL(btbl->cylsec), btbl->head, SEC(btbl->cylsec), btbl->cylsec, btbl->nsec); btbl++; }}intmain(int argc, char *argv[]){ int c; extern int optind; int opterr = 0; int larg = 0; int warg = 0; int garg = 0; while ((c = getopt(argc, argv, "lgw")) != -1) { switch(c) { case 'l': larg = 1; break; case 'w': warg = 1; break; case 'g': garg = 1; break; default: opterr++; break; } } argc -= optind; argv += optind; if (argc != 1) opterr++; if (opterr) Diag::fatal(1, "Usage: setboot disk_image\n"); target = argv[0]; int fd = open(target, O_RDWR); if (fd == -1) Diag::fatal(1, "setboot: can't open \"%s\"\n", argv[0]); if (larg) { ReadLoadList(fd); } else if (garg) { Geom geometry; GetGeometry(fd, geometry); Diag::printf("Geometry c/h/s: %d/%d/%d\n", geometry.cyl, geometry.hd, geometry.sec); } else { Geom geometry; GetGeometry(fd, geometry); UpdateBootTable(fd, geometry, warg); } close(fd); App.Exit();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -