summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--isys/Makefile2
-rw-r--r--isys/eddsupport.c311
-rw-r--r--isys/eddsupport.h9
-rw-r--r--isys/isys.c23
-rw-r--r--isys/isys.py12
-rw-r--r--kickstart.py6
-rw-r--r--loader2/Makefile2
-rw-r--r--loader2/hdinstall.c81
-rw-r--r--loader2/hdinstall.h1
-rw-r--r--loader2/kickstart.c4
-rw-r--r--loader2/loader.c7
11 files changed, 449 insertions, 9 deletions
diff --git a/isys/Makefile b/isys/Makefile
index 6937955c3..f0b536cd0 100644
--- a/isys/Makefile
+++ b/isys/Makefile
@@ -5,7 +5,7 @@ CFLAGS = -ffunction-sections -I$(PYTHONINCLUDE) -I.. -Wall -Os -g -DHAVE_NFS -D
OBJECTS = nfsmount.o nfsmount_clnt.o nfsmount_xdr.o imount.o getmacaddr.o \
smp.o devnodes.o cpio.o uncpio.o dasd.o \
lang.o isofs.o dns.o linkdetect.o pdc.o hpt.o silraid.o vio.o \
- ethtool.o getipaddr.o wireless.o
+ ethtool.o getipaddr.o wireless.o eddsupport.o
SOBJECTS = $(patsubst %.o,%.lo,$(OBJECTS))
SOURCES = $(patsubst %.o,%.c,$(OBJECTS)) isys.c
LOADLIBES = -lresolv -lpci -lpopt -lpump -lext2fs -lz -lbterm -lbogl -lwlite -lkudzu -lpci -lselinux
diff --git a/isys/eddsupport.c b/isys/eddsupport.c
new file mode 100644
index 000000000..72280c945
--- /dev/null
+++ b/isys/eddsupport.c
@@ -0,0 +1,311 @@
+/*
+ * eddsupport.c - handling of mapping disk drives in Linux to disk drives
+ * according to the BIOS using the edd kernel module
+ *
+ * Copyright 2004 Dell, Inc., Red Hat, Inc.
+ *
+ * Rezwanul_Kabir@Dell.com
+ * Jeremy Katz <katzj@redhat.com>
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * general public license.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/reboot.h>
+#include <sys/types.h>
+#include <linux/types.h>
+
+#include <kudzu/kudzu.h>
+
+
+#include "eddsupport.h"
+#include "isys.h"
+
+
+
+#define EDD_DIR "/sys/firmware/edd"
+#define SIG_FILE "mbr_signature"
+#define MBRSIG_OFFSET 0x1b8
+
+#define HASH_TABLE_SIZE 17
+
+struct diskMapEntry{
+ uint32_t key;
+ char *diskname;
+ struct diskMapEntry *next;
+};
+
+struct diskMapTable {
+ struct diskMapEntry **table;
+ int tableSize;
+};
+
+static struct diskMapTable *mbrSigToName = NULL;
+static int diskHashInit = 0;
+
+
+
+static struct diskMapTable* initializeHashTable(int);
+static int insertHashItem(struct diskMapTable *, struct diskMapEntry *);
+static struct diskMapEntry* lookupHashItem(struct diskMapTable *, uint32_t);
+static int addToHashTable(struct diskMapTable *, uint32_t , char *);
+static struct device ** createDiskList();
+static int mapBiosDisks(struct diskMapTable * , const char *);
+static int readDiskSig(char *, uint32_t *);
+static struct diskMapTable* uniqueSignatureExists(struct device **);
+static int readMbrSig(char *, uint32_t *);
+
+/* This is the top level function that creates a disk list present in the
+ * system, checks to see if unique signatures exist on the disks at offset
+ * 0x1b8. If a unique signature exists then it will map BIOS disks to their
+ * corresponding hd/sd device names. Otherwise, we'll avoid mapping drives.
+ */
+
+int probeBiosDisks() {
+ struct device ** devices = NULL;
+ struct diskMapTable *diskSigToName;
+
+ devices = createDiskList();
+ if(!devices){
+ fprintf(stderr, "No disks!\n");
+ return -1;
+ }
+
+ if(!(diskSigToName = uniqueSignatureExists(devices))) {
+ fprintf(stderr, "WARNING: Unique disk signatures don't exist\n");
+ return -1;
+ } else {
+ if(!mapBiosDisks(diskSigToName, EDD_DIR)){
+ fprintf(stderr, "WARNING: couldn't map BIOS disks\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+static struct device ** createDiskList(){
+ return probeDevices (CLASS_HD, BUS_UNSPEC, PROBE_ALL);
+}
+
+static struct diskMapTable * uniqueSignatureExists(struct device **devices) {
+ uint32_t current_sig, headsig;
+ struct device **devhead, **devlist;
+ int i;
+ struct diskMapTable *hashTable;
+
+ hashTable = initializeHashTable(HASH_TABLE_SIZE);
+ if(!hashTable){
+ fprintf(stderr, "Error initializing diskSigToName table\n");
+ return NULL;
+ }
+
+ for (devhead = devices, i = 0; (*devhead) != NULL; devhead++, i++) {
+ if (readDiskSig((*devhead)->device, &headsig) < 0) {
+ return NULL;
+ }
+
+ for (devlist = devhead + 1; (*devlist) != NULL; devlist++) {
+ if (readDiskSig((*devlist)->device, &current_sig) < 0)
+ return NULL;
+
+ if (headsig == current_sig)
+ return NULL;
+ }
+
+ if(!addToHashTable(hashTable, headsig, (*devhead)->device))
+ return NULL;
+ }
+
+ return hashTable;
+}
+
+
+static int readDiskSig(char *device, uint32_t *disksig) {
+ int fd, rc;
+
+ if (devMakeInode(device, "/tmp/biosdev")){
+ return -1;
+ }
+
+ fd = open("/tmp/biosdev", O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Error opening devce %s: %s\n ", device,
+ strerror(errno));
+ return -1;
+ }
+
+ rc = lseek(fd, MBRSIG_OFFSET, SEEK_SET);
+ if (rc < 0){
+ close(fd);
+
+ fprintf(stderr, "Error seeking to MBRSIG_OFFSET in %s: %s\n",
+ device, strerror(errno));
+ return -1;
+ }
+
+ rc = read(fd, disksig, sizeof(uint32_t));
+ if (rc < sizeof(uint32_t)) {
+ close(fd);
+
+ fprintf(stderr, "Failed to read signature from %s\n", device);
+ return -1;
+ }
+
+ unlink("/tmp/biosdev");
+ return 0;
+}
+
+static int mapBiosDisks(struct diskMapTable* hashTable,const char *path) {
+ DIR *dirHandle;
+ struct dirent *entry;
+ char * sigFileName;
+ uint32_t mbrSig, biosNum;
+ struct diskMapEntry *hashItem;
+
+ dirHandle = opendir(path);
+ if(!dirHandle){
+ fprintf(stderr, "Failed to open directory %s: %s\n", path,
+ strerror(errno));
+ return 0;
+ }
+
+ mbrSigToName = initializeHashTable(HASH_TABLE_SIZE);
+ if(!mbrSigToName){
+ fprintf(stderr, "Error initializing mbrSigToName table\n");
+ return 0;
+ }
+
+ while ((entry = readdir(dirHandle)) != NULL) {
+ if(!strncmp(entry->d_name,".",1) || !strncmp(entry->d_name,"..",2)) {
+ continue;
+ }
+ sscanf((entry->d_name+9), "%x", &biosNum);
+
+ sigFileName = malloc(strlen(path) + strlen(entry->d_name) + 20);
+ sprintf(sigFileName, "%s/%s/%s", path, entry->d_name, SIG_FILE);
+ if (readMbrSig(sigFileName, &mbrSig) == 0) {
+ hashItem = lookupHashItem(hashTable, mbrSig);
+ if (!hashItem)
+ return 0;
+ if(!addToHashTable(mbrSigToName, (uint32_t)biosNum,
+ hashItem->diskname))
+ return 0;
+ }
+ }
+ closedir(dirHandle);
+ return 1;
+}
+
+
+static int readMbrSig(char *filename, uint32_t *int_sig){
+ FILE* fh;
+
+ fh = fopen(filename,"r");
+ if(fh == NULL) {
+ fprintf(stderr, "Error opening mbr_signature file %s: %s\n", filename,
+ strerror(errno));
+ return -1;
+ }
+ fseek(fh, 0, SEEK_SET);
+ if (fscanf(fh, "%x", int_sig) != 1) {
+ fprintf(stderr, "Error reading %s\n", filename);
+ fclose(fh);
+ return -1;
+ }
+
+ fclose(fh);
+ return 0;
+}
+
+
+static struct diskMapTable* initializeHashTable(int size) {
+ struct diskMapTable *hashTable;
+
+ hashTable = malloc(sizeof(struct diskMapTable));
+ hashTable->tableSize = size;
+ hashTable->table = malloc(sizeof(struct diskMapEntry *) * size);
+ memset(hashTable->table,0,(sizeof(struct diskMapEntry *) * size));
+ return hashTable;
+}
+
+
+static int insertHashItem(struct diskMapTable *hashTable,
+ struct diskMapEntry *hashItem) {
+ int index;
+
+ index = (hashItem->key) % (hashTable->tableSize);
+
+ if(hashTable->table[index] == NULL){
+ hashTable->table[index] = hashItem;
+ return index;
+ } else {
+ hashItem->next = hashTable->table[index];
+ hashTable->table[index] = hashItem;
+ return index;
+ }
+}
+
+
+static struct diskMapEntry * lookupHashItem(struct diskMapTable *hashTable,
+ uint32_t itemKey) {
+ int index;
+ struct diskMapEntry *hashItem;
+
+ index = itemKey % (hashTable->tableSize);
+ for (hashItem = hashTable->table[index];
+ (hashItem != NULL) && (hashItem->key != itemKey);
+ hashItem = hashItem->next) {
+ ;
+ }
+ return hashItem;
+}
+
+
+static int addToHashTable(struct diskMapTable *hashTable,
+ uint32_t itemKey, char *diskName) {
+ int index;
+ struct diskMapEntry *diskSigToNameEntry;
+
+ diskSigToNameEntry = malloc(sizeof(struct diskMapEntry));
+ diskSigToNameEntry->next = NULL;
+ diskSigToNameEntry->key = itemKey;
+ diskSigToNameEntry->diskname = diskName;
+
+ if ((index = insertHashItem(hashTable, diskSigToNameEntry)) < 0){
+ fprintf(stderr, "Unable to insert item\n");
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+
+char * getBiosDisk(char *biosStr) {
+ uint32_t biosNum;
+
+ if (diskHashInit == 0) {
+ probeBiosDisks();
+ diskHashInit = 1;
+ }
+
+ if (mbrSigToName == NULL)
+ return NULL;
+
+ sscanf(biosStr,"%x",&biosNum);
+ return lookupHashItem(mbrSigToName, biosNum)->diskname;
+}
diff --git a/isys/eddsupport.h b/isys/eddsupport.h
new file mode 100644
index 000000000..b7a390f43
--- /dev/null
+++ b/isys/eddsupport.h
@@ -0,0 +1,9 @@
+#ifndef EDDSUPPORT_H
+#define EDDSUPPORT_H
+
+int probeBiosDisks();
+char* getBiosDisk(char *);
+
+#endif
+
+
diff --git a/isys/isys.c b/isys/isys.c
index d16538871..164e5ea2e 100644
--- a/isys/isys.c
+++ b/isys/isys.c
@@ -49,6 +49,7 @@
#include "lang.h"
#include "getmacaddr.h"
#include "wireless.h"
+#include "eddsupport.h"
#ifndef CDROMEJECT
#define CDROMEJECT 0x5309
@@ -111,6 +112,8 @@ static PyObject * doGetMacAddress(PyObject * s, PyObject * args);
static PyObject * doGetIPAddress(PyObject * s, PyObject * args);
static PyObject * doResetFileContext(PyObject * s, PyObject * args);
static PyObject * isWireless(PyObject * s, PyObject * args);
+static PyObject * doProbeBiosDisks(PyObject * s, PyObject * args);
+static PyObject * doGetBiosDisk(PyObject * s, PyObject * args);
static PyMethodDef isysModuleMethods[] = {
{ "ejectcdrom", (PyCFunction) doEjectCdrom, METH_VARARGS, NULL },
@@ -168,6 +171,8 @@ static PyMethodDef isysModuleMethods[] = {
{ "getIPAddress", (PyCFunction) doGetIPAddress, METH_VARARGS, NULL},
{ "resetFileContext", (PyCFunction) doResetFileContext, METH_VARARGS, NULL },
{ "isWireless", (PyCFunction) isWireless, METH_VARARGS, NULL },
+ { "biosDiskProbe", (PyCFunction) doProbeBiosDisks, METH_VARARGS,NULL},
+ { "getbiosdisk",(PyCFunction) doGetBiosDisk, METH_VARARGS,NULL},
{ NULL }
} ;
@@ -1435,3 +1440,21 @@ static PyObject * start_bterm(PyObject * s, PyObject * args) {
return Py_BuildValue("i", isysStartBterm());
}
+
+static PyObject * doProbeBiosDisks(PyObject * s, PyObject * args) {
+ if (!PyArg_ParseTuple(args, "")) return NULL;
+
+
+ return Py_BuildValue("i", probeBiosDisks());
+}
+
+static PyObject * doGetBiosDisk(PyObject * s, PyObject * args) {
+ char *mbr_sig;
+ char *diskname;
+
+ if (!PyArg_ParseTuple(args, "s", &mbr_sig)) return NULL;
+
+ diskname = getBiosDisk(mbr_sig);
+ return Py_BuildValue("s", diskname);
+
+}
diff --git a/isys/isys.py b/isys/isys.py
index 4a2fd59a0..3a850f553 100644
--- a/isys/isys.py
+++ b/isys/isys.py
@@ -1,10 +1,11 @@
#
-# isys.py - installer utilitiy functions and glue for C module
+# isys.py - installer utility functions and glue for C module
#
# Matt Wilson <msw@redhat.com>
# Erik Troan <ewt@redhat.com>
+# Jeremy Katz <katzj@redhat.com>
#
-# Copyright 2001 Red Hat, Inc.
+# Copyright 2001 - 2004 Red Hat, Inc.
#
# This software may be freely redistributed under the terms of the GNU
# library public license.
@@ -724,6 +725,13 @@ def resetFileContext(fn):
def startBterm():
return _isys.startBterm()
+def doProbeBiosDisks():
+ return _isys.biosDiskProbe()
+
+def doGetBiosDisk(mbrSig):
+ return _isys.getbiosdisk(mbrSig)
+
+
printObject = _isys.printObject
bind_textdomain_codeset = _isys.bind_textdomain_codeset
isVioConsole = _isys.isVioConsole
diff --git a/kickstart.py b/kickstart.py
index a3b783c24..f25274ec8 100644
--- a/kickstart.py
+++ b/kickstart.py
@@ -1138,7 +1138,7 @@ class KickstartBase(BaseInstallClass):
'type=', 'fstype=', 'asprimary',
'noformat', 'start=', 'end=',
'badblocks', 'recommended',
- 'ondrive='])
+ 'ondrive=', 'onbiosdisk=' ])
for n in args:
(str, arg) = n
@@ -1152,6 +1152,10 @@ class KickstartBase(BaseInstallClass):
onPart = arg
elif str == '--ondisk' or str == '--ondrive':
disk = arg
+ elif str == '--onbiosdisk':
+ disk = isys.doGetBiosDisk(arg)
+ if disk is None:
+ raise KickstartValueError, "Specified BIOS disk %s cannot be determined" %(arg,)
elif str == '--bytes-per-inode':
fsopts = ['-i', arg]
# XXX this doesn't do anything right now
diff --git a/loader2/Makefile b/loader2/Makefile
index 0fae6a689..e628454ec 100644
--- a/loader2/Makefile
+++ b/loader2/Makefile
@@ -16,7 +16,7 @@ GUNZIP = -lz
BINS = loader
HWOBJS = pcmcia.o usb.o firewire.o hardware.o
-METHOBJS = method.o cdinstall.o hdinstall.o nfsinstall.o urlinstall.o
+METHOBJS = method.o cdinstall.o hdinstall.o nfsinstall.o urlinstall.o
OBJS = log.o moduleinfo.o loadermisc.o modules.o moduledeps.o windows.o \
lang.o kbd.o modstubs.o driverdisk.o selinux.o \
md5.o mediacheck.o kickstart.o driverselect.o \
diff --git a/loader2/hdinstall.c b/loader2/hdinstall.c
index 5da43a983..31d9b4c87 100644
--- a/loader2/hdinstall.c
+++ b/loader2/hdinstall.c
@@ -40,7 +40,7 @@
#include "../isys/imount.h"
#include "../isys/isys.h"
-
+#include "../isys/eddsupport.h"
/* pull in second stage image for hard drive install */
@@ -447,14 +447,17 @@ char * mountHardDrive(struct installMethod * method,
void setKickstartHD(struct loaderData_s * loaderData, int argc,
char ** argv, int * flagsPtr) {
- char *partition, *dir;
+ char *biospart, *partition, *dir, *p;
poptContext optCon;
int rc;
+
struct poptOption ksHDOptions[] = {
+ { "biospart", '\0', POPT_ARG_STRING, &biospart, 0 },
{ "partition", '\0', POPT_ARG_STRING, &partition, 0 },
{ "dir", '\0', POPT_ARG_STRING, &dir, 0 },
{ 0, 0, 0, 0, 0 }
};
+
logMessage("kickstartFromHD");
optCon = poptGetContext(NULL, argc, (const char **) argv, ksHDOptions, 0);
@@ -468,6 +471,24 @@ void setKickstartHD(struct loaderData_s * loaderData, int argc,
return;
}
+ if (biospart) {
+ char * dev;
+
+ p = strchr(biospart,'p');
+ if(!p){
+ logMessage("Bad argument for --biospart");
+ return;
+ }
+ *p = '\0';
+ dev = getBiosDisk(biospart);
+ if (dev == NULL) {
+ logMessage("Unable to location BIOS partition %s", biospart);
+ return;
+ }
+ partition = malloc(strlen(dev) + strlen(p) + 2);
+ sprintf(partition, "%s%s", dev, p);
+ }
+
loaderData->method = strdup("hd");
loaderData->methodData = calloc(sizeof(struct hdInstallData *), 1);
if (partition)
@@ -518,3 +539,59 @@ int kickstartFromHD(char *kssrc, int flags) {
return 0;
}
+
+
+int kickstartFromBD(char *kssrc, int flags) {
+ int rc;
+ char *p, *q = NULL, *r = NULL, *tmpstr, *ksdev, *kspath, *biosksdev;
+
+ logMessage("getting kickstart file from biosdrive");
+
+ /* format is ks=bd:[device]:/path/to/ks.cfg */
+ /* split of pieces */
+ tmpstr = strdup(kssrc);
+ p = strchr(tmpstr, ':');
+ if (p)
+ q = strchr(p+1, ':');
+
+ if (!p || !q) {
+ logMessage("Format of command line is ks=bd:device:/path/to/ks.cfg");
+ free(tmpstr);
+ return 1;
+ }
+
+ *q = '\0';
+ kspath = q+1;
+
+ r = strchr(p+1,'p');
+ if(!r){
+ logMessage("Format of biosdisk is 80p1");
+ free(tmpstr);
+ return 1;
+ }
+
+ *r = '\0';
+ biosksdev = getBiosDisk((p + 1));
+ if(!biosksdev){
+ startNewt(flags);
+ newtWinMessage(_("Error"), _("OK"),
+ _("Cannot find hard drive for BIOS disk %s"),
+ p + 1);
+ return 1;
+ }
+
+
+ ksdev = malloc(strlen(biosksdev) + 3);
+ sprintf(ksdev, "%s%s", biosksdev, r + 1);
+ logMessage("Loading ks from device %s on path %s", ksdev, kspath);
+ if ((rc=getKickstartFromBlockDevice(ksdev, kspath))) {
+ if (rc == 3) {
+ startNewt(flags);
+ newtWinMessage(_("Error"), _("OK"),
+ _("Cannot find kickstart file on hard drive."));
+ }
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/loader2/hdinstall.h b/loader2/hdinstall.h
index c4277a41e..5f4293e3f 100644
--- a/loader2/hdinstall.h
+++ b/loader2/hdinstall.h
@@ -16,5 +16,6 @@ char * mountHardDrive(struct installMethod * method,
moduleInfoSet modInfo, moduleList modLoaded,
moduleDeps * modDepsPtr, int flags);
int kickstartFromHD(char *kssrc, int flags);
+int kickstartFromBD(char *kssrc, int flags);
#endif
diff --git a/loader2/kickstart.c b/loader2/kickstart.c
index 20dc733d6..1d3d3b81e 100644
--- a/loader2/kickstart.c
+++ b/loader2/kickstart.c
@@ -330,6 +330,10 @@ void getKickstartFile(struct loaderData_s * loaderData, int * flagsPtr) {
if (kickstartFromHD(c, *flagsPtr))
return;
loaderData->ksFile = strdup("/tmp/ks.cfg");
+ } else if (!strncmp(c, "ks=bd:", 6)) {
+ if (kickstartFromBD(c, *flagsPtr))
+ return;
+ loaderData->ksFile = strdup("/tmp/ks.cfg");
} else if (!strncmp(c, "ks=cdrom", 8)) {
if (kickstartFromCD(c, *flagsPtr))
return;
diff --git a/loader2/loader.c b/loader2/loader.c
index 28ec832da..44163fb56 100644
--- a/loader2/loader.c
+++ b/loader2/loader.c
@@ -80,6 +80,7 @@
#include "../isys/isys.h"
#include "../isys/stubs.h"
#include "../isys/lang.h"
+#include "../isys/eddsupport.h"
/* maximum number of extra arguments that can be passed to the second stage */
#define MAX_EXTRA_ARGS 128
@@ -1168,6 +1169,7 @@ int main(int argc, char ** argv) {
memset(&loaderData, 0, sizeof(loaderData));
+
extraArgs[0] = NULL;
flags = parseCmdLineFlags(flags, &loaderData, cmdLine);
@@ -1195,8 +1197,8 @@ int main(int argc, char ** argv) {
if (isVioConsole())
setenv("TERM", "vt100", 1);
- mlLoadModuleSet("cramfs:vfat:nfs:loop:isofs:floppy", modLoaded, modDeps,
- modInfo, flags);
+ mlLoadModuleSet("cramfs:vfat:nfs:loop:isofs:floppy:edd",
+ modLoaded, modDeps, modInfo, flags);
/* now let's do some initial hardware-type setup */
ideSetup(modLoaded, modDeps, modInfo, flags);
@@ -1253,6 +1255,7 @@ int main(int argc, char ** argv) {
getDDFromSource(&loaderData, loaderData.ddsrc, flags);
}
+
/* JKFIXME: loaderData->ksFile is set to the arg from the command line,
* and then getKickstartFile() changes it and sets FL_KICKSTART.
* kind of weird. */