Initial revision

This commit is contained in:
Anton Kachalov 2004-01-20 18:32:43 +00:00
commit 46438969c6
96 changed files with 19815 additions and 0 deletions

11
.cvsignore Normal file
View File

@ -0,0 +1,11 @@
init
stage1-full
stage1-cdrom
stage1-disk
stage1-network
debug.log
.depend
*.rdz*
mkinitrd_helper.tar.bz2
hack_*
stage1-usbnet

24
MANIFEST.doc Normal file
View File

@ -0,0 +1,24 @@
#
# Master Manifest file for documentation-only distribution
#
doc d
MANIFEST.doc f
doc/article.ps f
doc/rose94.ps f
doc/bash.ps f
doc/bashbug.ps f
doc/builtins.ps f
doc/rbash.ps f
doc/bashref.ps f
doc/bashref.dvi f
doc/bash.0 f
doc/bashbug.0 f
doc/builtins.0 f
doc/rbash.0 f
doc/article.txt f
doc/bash.html f
doc/bashref.html f
doc/article.pdf f
doc/bash.pdf f
doc/bashref.pdf f
doc/rose94.pdf f

265
Makefile Normal file
View File

@ -0,0 +1,265 @@
#******************************************************************************
#
# mdk-stage1 - the program that will load second-stage install
#
# $Id$
#
# Guillaume Cottenceau (gc@mandrakesoft.com)
#
# Copyright 2000 MandrakeSoft
#
# This software may be freely redistributed under the terms of the GNU
# 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.
#
# Portions from Erik Troan (ewt@redhat.com) Copyright 1996 Red Hat Software
#
#*****************************************************************************
#
# Currently:
#
# ix86
# init with minilibc
# stage1 with dietlibc except some targets
#
# ppc
# init with dietlibc
# stage1 with glibc
#
# ia64
# init with glibc
# stage1 with glibc
#
#*****************************************************************************
top_dir = .
include $(top_dir)/Makefile.common
include $(TOP)/config
VERSION = $(CFGversion)
DEFS = -DVERSION=\"$(VERSION)\" -DSPAWN_SHELL -DDISTRIB_NAME=\"$(CFGdistribname)\"
COMPILE = $(CC) $(DEFS) $(CFLAGS)
#- stage1 "loader"
ifeq (i386, $(ARCH))
INITSRC = minilibc.c init.c
INIT_DEFS = -DINIT_HEADERS=\"minilibc.h\"
else
INITSRC = init.c
ifeq (ia64, $(ARCH))
INIT_DEFS = -DINIT_HEADERS=\"init-libc-headers.h\" $(GLIBC_INCLUDES)
else
INIT_DEFS = -DINIT_HEADERS=\"init-libc-headers.h\" $(DIETLIBC_INCLUDES)
endif
endif
INITOBJS = $(subst .c,.o,$(INITSRC))
#- frontends
NEWT_FRONTEND_SRC = newt-frontend.c
GLIBC_NEWT_FRONTEND_LIBS = newt/libnewt.a slang/libslang.a
DIETLIBC_NEWT_FRONTEND_LIBS = $(subst .a,-DIET.a,$(GLIBC_NEWT_FRONTEND_LIBS))
STDIO_FRONTEND_SRC = stdio-frontend.c
GLIBC_STDIO_FRONTEND_LIBS =
DIETLIBC_STDIO_FRONTEND_LIBS =
FRONTEND_OBJS = $(subst .c,.o,$($(F)_FRONTEND_SRC))
FRONTEND_LINK = $(FRONTEND_OBJS) $($(L)_$(F)_FRONTEND_LIBS)
ifeq (i386, $(ARCH))
# INSMOD = insmod-busybox
INSMOD = insmod-modutils
else
INSMOD = insmod-modutils
endif
GLIBC_STAGE1_OWN_LIBS = $(INSMOD)/libinsmod.a mar/libmar.a bzlib/libbz2.a
#$(top_dir)/$(TMP_PKG)/usr/lib/libbz2.a
DIETLIBC_STAGE1_OWN_LIBS = $(subst .a,-DIET.a,$(GLIBC_STAGE1_OWN_LIBS))
STAGE1_OWN_LIBS = $($(L)_STAGE1_OWN_LIBS)
ifeq (DIETLIBC, $(L))
STAGE1_NETWORK_LIBS = $(top_dir)/$(TMP_PKG)/usr/lib/dietlibc/lib-$(ARCH)/librpc.a
endif
ifeq (GLIBC, $(L))
STAGE1_NETWORK_LIBS = /usr/lib/libresolv.a
endif
#- stage1 itself
STAGE1SRC = stage1.c log.c tools.c modules.c probing.c mount.c automatic.c frontend-common.c
CDROMSRC = cdrom.c
DISKSRC = disk.c lomount.c
NETWORKSRC = network.c nfsmount.c dhcp.c url.c dns.c adsl.c
ALLSRC = $(INITSRC) $(STAGE1SRC) $(CDROMSRC) $(DISKSRC) $(NETWORKSRC)
STAGE1OBJS-CDROM = $(subst .c,-CDROM.o,$(STAGE1SRC) $(CDROMSRC))
CDROM_DEFS = -DDISABLE_DISK -DDISABLE_NETWORK -DAUTO_METHOD=\""cdrom"\"
STAGE1OBJS-DISK = $(subst .c,-DISK.o,$(STAGE1SRC) $(DISKSRC))
DISK_DEFS = -DDISABLE_CDROM -DDISABLE_NETWORK -DAUTO_METHOD=\""disk"\"
STAGE1OBJS-NETWORK = $(subst .c,-NETWORK.o,$(STAGE1SRC) $(NETWORKSRC))
NETWORK_DEFS = -DDISABLE_CDROM -DDISABLE_DISK
STAGE1OBJS-USBNET = $(subst .c,-USBNET.o,$(STAGE1SRC) $(NETWORKSRC))
STAGE1OBJS-FULL = $(subst .c,-FULL.o,$(STAGE1SRC) $(CDROMSRC) $(DISKSRC) $(NETWORKSRC))
ifeq (i386, $(ARCH))
LDFLAGS_INIT = -static -nostdlib /usr/lib/crt1.o
else
ifeq (ia64, $(ARCH))
LDFLAGS_INIT = $(GLIBC_LDFLAGS_STAGE1)
INIT_LIBC = $(GLIBC_LIBC)
else
LDFLAGS_INIT = $(DIETLIBC_LDFLAGS_STAGE1)
INIT_LIBC = $(DIETLIBC_LIBC)
endif
endif
BINS = init stage1-full
ifeq (i386, $(ARCH))
BINS += stage1-cdrom stage1-disk stage1-network stage1-usbnet
endif
#DIRS += mar pci-resource usb-resource $(INSMOD) slang newt ppp/pppd rp-pppoe/src
DIRS += mar pci-resource usb-resource $(INSMOD) slang newt bzlib ppp/pppd rp-pppoe/src
ifeq (i386,$(ARCH))
DIRS += pcmcia
endif
ifeq (i386,$(ARCH))
GLIBC_PCMCIA_LIB = pcmcia/libpcmcia.a
DIETLIBC_PCMCIA_LIB = $(subst .a,-DIET.a,$(GLIBC_PCMCIA_LIB))
PCMCIA_LIB = $($(L)_PCMCIA_LIB)
PCMCIA_DEFS = -DENABLE_PCMCIA
endif
USBNET_DEFS_GEN = -DENABLE_USB -DENABLE_USBNET
USBNET_DEFS = $(USBNET_DEFS_GEN) -DDISABLE_PCINET
all: unpack dirs $(BINS)
unpack:
rm -rf $(top_dir)/$(TMP_PKG)
mkdir $(top_dir)/$(TMP_PKG)
pushd $(top_dir)/$(TMP_PKG); \
for f in `cat $(top_dir)/../REQ`; do \
rpm2cpio $(CFGrepo)/$$f-*.rpm | cpio -id; \
done
dirs:
@for n in . $(DIRS); do \
[ "$$n" = "." ] || make -C $$n ;\
done
init: $(INITOBJS) $(INIT_LIBC)
$(CC) -o $@ $^ $(LDFLAGS_INIT)
$(STRIPCMD) $@
stage1-cdrom: $(STAGE1OBJS-CDROM) $(STAGE1_OWN_LIBS) $(FRONTEND_LINK) $(STAGE1_LIBC)
$(CC) -o $@ $^ $(LDFLAGS_STAGE1)
$(STRIPCMD) $@
stage1-disk: $(STAGE1OBJS-DISK) $(STAGE1_OWN_LIBS) $(FRONTEND_LINK) $(STAGE1_LIBC)
$(CC) -o $@ $^ $(LDFLAGS_STAGE1)
$(STRIPCMD) $@
stage1-network: $(STAGE1OBJS-NETWORK) $(STAGE1_OWN_LIBS) $(STAGE1_NETWORK_LIBS) $(FRONTEND_LINK) $(STAGE1_LIBC)
$(CC) -o $@ $^ $(LDFLAGS_STAGE1)
$(STRIPCMD) $@
stage1-usbnet: $(STAGE1OBJS-USBNET) $(STAGE1_OWN_LIBS) $(STAGE1_NETWORK_LIBS) $(FRONTEND_LINK) $(STAGE1_LIBC)
$(CC) -o $@ $^ $(LDFLAGS_STAGE1)
$(STRIPCMD) $@
stage1-full: $(STAGE1OBJS-FULL) $(STAGE1_OWN_LIBS) $(STAGE1_NETWORK_LIBS) $(FRONTEND_LINK) $(PCMCIA_LIB) $(STAGE1_LIBC)
$(CC) -o $@ $^ $(LDFLAGS_STAGE1)
$(STRIPCMD) $@
$(INITOBJS): %.o: %.c
$(COMPILE) $(INIT_DEFS) -c $<
$(STAGE1OBJS-CDROM): %-CDROM.o: %.c
$(COMPILE) $(INCLUDES) $(CDROM_DEFS) -c $< -o $@
$(STAGE1OBJS-DISK): %-DISK.o: %.c
$(COMPILE) $(INCLUDES) $(DISK_DEFS) -c $< -o $@
$(STAGE1OBJS-NETWORK): %-NETWORK.o: %.c
$(COMPILE) $(INCLUDES) $(NETWORK_DEFS) -c $< -o $@
$(STAGE1OBJS-USBNET): %-USBNET.o: %.c
$(COMPILE) $(INCLUDES) $(NETWORK_DEFS) $(USBNET_DEFS) -c $< -o $@
$(STAGE1OBJS-FULL): %-FULL.o: %.c
$(COMPILE) $(INCLUDES) $(USBNET_DEFS_GEN) $(PCMCIA_DEFS) -c $< -o $@
.c.o:
$(COMPILE) $(INCLUDES) -c $<
clean:
@for n in $(DIRS); do \
(cd $$n; make clean) \
done
rm -f *.o .depend *.rdz *.img $(BINS)
tar-mkinitrd_helper: clean
rm -rf mkinitrd_helper-subdir
mkdir mkinitrd_helper-subdir
cd mkinitrd_helper-subdir ; cp -a ../dietlibc ../insmod-busybox ../Makefile.common ../insmod.h ../log.h . ; \
cp ../Makefile.mkinitrd_helper Makefile
tar cfj mkinitrd_helper.tar.bz2 mkinitrd_helper-subdir --exclude CVS
rm -rf mkinitrd_helper-subdir
.depend:
$(CPP) $(CFLAGS) -M $(ALLSRC) > .depend
ifeq (.depend,$(wildcard .depend))
include .depend
endif
*-CDROM.o: %-CDROM.o: %.o
*-DISK.o: %-DISK.o: %.o
*-NETWORK.o: %-NETWORK.o: %.o
*-USBNET.o: %-USBNET.o: %.o
*-FULL.o: %-FULL.o: %.o

59
Makefile.common Normal file
View File

@ -0,0 +1,59 @@
# -*- makefile -*-
#******************************************************************************
#
# Guillaume Cottenceau (gc@mandrakesoft.com)
#
# Copyright 2000 MandrakeSoft
#
# This software may be freely redistributed under the terms of the GNU
# 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.
#
#*****************************************************************************
ARCH := $(patsubst i%86,i386,$(shell uname -m))
ARCH := $(patsubst sparc%,sparc,$(ARCH))
#- default lib is dietlibc (honoured by main Makefile whenever possible)
L = DIETLIBC
#L = GLIBC
#- default frontend is newt (honoured by main Makefile whenever possible)
F = NEWT
# F = STDIO
#- override in some situations
ifeq (ia64, $(ARCH))
L = GLIBC
endif
ifeq (ppc, $(ARCH))
L = GLIBC
endif
TMP_PKG=tmp_rpm
#- flags used by all stuff
ifeq (ppc, $(ARCH))
CFLAGS = -Os -pipe -Wall -fomit-frame-pointer
else
CFLAGS = -Os -pipe -Wall -fomit-frame-pointer -D_BSD_SOURCE -D_GNU_SOURCE -D__LIBC_DIETLIBC__
endif
DIETLIBC_INCLUDES = -I$(top_dir)/$(TMP_PKG)/usr/lib/dietlibc/include -I. -I$(top_dir)/$(TMP_PKG)/usr/include
GLIBC_INCLUDES = -I. -I$(top_dir)/$(TMP_PKG)/usr/include
# -I$(top_dir)/$(TMP_PKG)/usr/lib/dietlibc/include -I$(top_dir)/$(TMP_PKG)/usr/include
INCLUDES = $($(L)_INCLUDES)
GLIBC_LDFLAGS_STAGE1 = -static
DIETLIBC_LDFLAGS_STAGE1 = -nostdlib $(top_dir)/$(TMP_PKG)/usr/lib/dietlibc/lib-$(ARCH)/start.o -L/usr/lib/gcc-lib/i*86-alt-linux/3.*/ -lgcc
LDFLAGS_STAGE1 = $($(L)_LDFLAGS_STAGE1)
GLIBC_LIBC =
DIETLIBC_LIBC = $(top_dir)/$(TMP_PKG)/usr/lib/dietlibc/lib-$(ARCH)/libc.a $(top_dir)/$(TMP_PKG)/usr/lib/dietlibc/lib-$(ARCH)/libcompat.a
STAGE1_LIBC = $($(L)_LIBC)
STRIPCMD = strip -R .note -R .comment

30
Makefile.mkinitrd_helper Normal file
View File

@ -0,0 +1,30 @@
#******************************************************************************
#
# Guillaume Cottenceau (gc@mandrakesoft.com)
#
# Copyright 2000 MandrakeSoft
#
# This software may be freely redistributed under the terms of the GNU
# 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.
#
#*****************************************************************************
DIRS = dietlibc insmod-busybox
all: dirs
dirs:
@for n in . $(DIRS); do \
[ "$$n" = "." ] || make -C $$n ;\
done
clean:
@for n in $(DIRS); do \
(cd $$n; make clean) \
done

3
REQ Normal file
View File

@ -0,0 +1,3 @@
bzlib-devel
bzlib-devel-static
dietlibc

172
adsl.c Normal file
View File

@ -0,0 +1,172 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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 <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
// #include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdio.h>
#include <resolv.h>
#include <signal.h>
#include "stage1.h"
#include "log.h"
#include "network.h"
#include "modules.h"
#include "tools.h"
#include "frontend.h"
#include "automatic.h"
#include "adsl.h"
static enum return_type adsl_connect(char * net_device, char * username, char * password)
{
char pppoe_call[500];
char * pppd_launch[] = { "/sbin/pppd", "pty", pppoe_call, "noipdefault", "noauth", "default-asyncmap", "defaultroute",
"hide-password", "nodetach", "usepeerdns", "local", "mtu", "1492", "mru", "1492", "noaccomp",
"noccp", "nobsdcomp", "nodeflate", "nopcomp", "novj", "novjccomp", "user", username,
"password", password, "lcp-echo-interval", "20", "lcp-echo-failure", "3", "lock", "persist", NULL };
int fd;
int retries = 10;
char * tty_adsl = "/dev/tty6";
enum return_type status = RETURN_ERROR;
pid_t ppp_pid;
snprintf(pppoe_call, sizeof(pppoe_call), "/sbin/pppoe -p /var/run/pppoe.conf-adsl.pid.pppoe -I %s -T 80 -U -m 1412", net_device);
fd = open(tty_adsl, O_RDWR);
if (fd == -1) {
log_message("cannot open tty -- no pppd");
return RETURN_ERROR;
}
else if (access(pppd_launch[0], X_OK)) {
log_message("cannot open pppd - %s doesn't exist", pppd_launch[0]);
return RETURN_ERROR;
}
if (!(ppp_pid = fork())) {
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
close(fd);
setsid();
if (ioctl(0, TIOCSCTTY, NULL))
log_perror("could not set new controlling tty");
printf("\t(exec of pppd)\n");
execve(pppd_launch[0], pppd_launch, grab_env());
log_message("execve of %s failed: %s", pppd_launch[0], strerror(errno));
exit(-1);
}
close(fd);
while (retries > 0 && kill(ppp_pid, 0) == 0) {
FILE * f;
if ((f = fopen("/var/run/pppd.tdb", "rb"))) {
while (1) {
char buf[500];
if (!fgets(buf, sizeof(buf), f))
break;
if (strstr(buf, "IPLOCAL="))
status = RETURN_OK;
}
fclose(f);
if (status == RETURN_OK) {
log_message("PPP: connected!");
break;
}
}
retries--;
log_message("PPP: <sleep>");
sleep(2);
}
if (status != RETURN_OK) {
log_message("PPP: could not connect");
kill(ppp_pid, SIGTERM);
sleep(1);
kill(ppp_pid, SIGKILL);
sleep(1);
}
return status;
}
enum return_type perform_adsl(struct interface_info * intf)
{
struct in_addr addr;
char * questions[] = { "Username", "Password", NULL };
char * questions_auto[] = { "adsluser", "adslpass", NULL };
static char ** answers = NULL;
enum return_type results;
inet_aton("10.0.0.10", &addr);
memcpy(&intf->ip, &addr, sizeof(addr));
inet_aton("255.255.255.0", &addr);
memcpy(&intf->netmask, &addr, sizeof(addr));
*((uint32_t *) &intf->broadcast) = (*((uint32_t *) &intf->ip) &
*((uint32_t *) &intf->netmask)) | ~(*((uint32_t *) &intf->netmask));
intf->is_ptp = 0;
if (configure_net_device(intf)) {
stg1_error_message("Could not configure..");
return RETURN_ERROR;
}
results = ask_from_entries_auto("Please enter the username and password for your ADSL account.\n"
"(Warning! only PPPoE protocol is supported)",
questions, &answers, 40, questions_auto, NULL);
if (results != RETURN_OK)
return results;
intf->boot_proto = BOOTPROTO_ADSL_PPPOE;
wait_message("Waiting for ADSL connection to show up...");
my_insmod("ppp_generic", ANY_DRIVER_TYPE, NULL);
my_insmod("ppp_async", ANY_DRIVER_TYPE, NULL);
my_insmod("ppp", ANY_DRIVER_TYPE, NULL);
results = adsl_connect(intf->device, answers[0], answers[1]);
remove_wait_message();
if (results != RETURN_OK) {
wait_message("Retrying the ADSL connection...");
results = adsl_connect(intf->device, answers[0], answers[1]);
remove_wait_message();
} else {
intf->user = strdup(answers[0]);
intf->pass = strdup(answers[1]);
}
if (results != RETURN_OK) {
stg1_error_message("I could not connect to the ADSL network.");
return perform_adsl(intf);
}
sleep(1);
res_init(); /* reinit the resolver, pppd modified /etc/resolv.conf */
return RETURN_OK;
}

34
adsl.h Normal file
View File

@ -0,0 +1,34 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* View the homepage: http://us.mandrakesoft.com/~gc/html/stage1.html
*
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from GRUB -- GRand Unified Bootloader
* Copyright (C) 2000 Free Software Foundation, Inc.
*
* Itself based on etherboot-4.6.4 by Martin Renters.
*
*/
#ifndef _ADSL_H_
#define _ADSL_H_
#include "stage1.h"
#include "network.h"
enum return_type perform_adsl(struct interface_info * intf);
#endif

162
automatic.c Normal file
View File

@ -0,0 +1,162 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* This is supposed to replace the redhat "kickstart", by name but
* also by design (less code pollution).
*
*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "tools.h"
#include "stage1.h"
#include "frontend.h"
#include "log.h"
#include "automatic.h"
static struct param_elem * automatic_params;
static char * value_not_bound = "";
void grab_automatic_params(char * line)
{
int i, p;
struct param_elem tmp_params[50];
i = 0; p = 0;
while (line[i] != '\0') {
char *name, *value;
int k;
int j = i;
while (line[i] != ':' && line[i] != '\0')
i++;
name = memdup(&line[j], i-j + 1);
name[i-j] = 0;
k = i+1;
i++;
while (line[i] != ',' && line[i] != '\0')
i++;
value = memdup(&line[k], i-k + 1);
value[i-k] = 0;
tmp_params[p].name = name;
tmp_params[p].value = value;
p++;
if (line[i] == '\0')
break;
i++;
}
tmp_params[p++].name = NULL;
automatic_params = memdup(tmp_params, sizeof(struct param_elem) * p);
log_message("AUTOMATIC MODE: got %d params", p-1);
}
char * get_auto_value(char * auto_param)
{
struct param_elem * ptr = automatic_params;
while (ptr->name) {
if (!strcmp(ptr->name, auto_param))
return ptr->value;
ptr++;
}
return value_not_bound;
}
enum return_type ask_from_list_auto(char *msg, char ** elems, char ** choice, char * auto_param, char ** elems_auto)
{
#ifndef AUTO_METHOD
if (!IS_AUTOMATIC)
return ask_from_list(msg, elems, choice);
else
#endif
{
char ** sav_elems = elems;
#ifdef AUTO_METHOD
char * tmp = AUTO_METHOD;
#else
char * tmp = get_auto_value(auto_param);
#endif
while (elems && *elems) {
if (!strcmp(tmp, *elems_auto)) {
*choice = *elems;
log_message("AUTOMATIC: parameter %s for %s means returning %s", tmp, auto_param, *elems);
return RETURN_OK;
}
elems++;
elems_auto++;
}
unset_param(MODE_AUTOMATIC); /* we are in a fallback mode */
return ask_from_list(msg, sav_elems, choice);
}
}
enum return_type ask_from_list_comments_auto(char *msg, char ** elems, char ** elems_comments, char ** choice, char * auto_param, char ** elems_auto)
{
#ifndef AUTO_METHOD
if (!IS_AUTOMATIC)
return ask_from_list_comments(msg, elems, elems_comments, choice);
else
#endif
{
char ** sav_elems = elems;
#ifdef AUTO_METHOD
char * tmp = AUTO_METHOD;
#else
char * tmp = get_auto_value(auto_param);
#endif
while (elems && *elems) {
if (!strcmp(tmp, *elems_auto)) {
*choice = *elems;
log_message("AUTOMATIC: parameter %s for %s means returning %s", tmp, auto_param, *elems);
return RETURN_OK;
}
elems++;
elems_auto++;
}
unset_param(MODE_AUTOMATIC); /* we are in a fallback mode */
return ask_from_list_comments(msg, sav_elems, elems_comments, choice);
}
}
enum return_type ask_from_entries_auto(char *msg, char ** questions, char *** answers, int entry_size, char ** questions_auto, void (*callback_func)(char ** strings))
{
if (!IS_AUTOMATIC)
return ask_from_entries(msg, questions, answers, entry_size, callback_func);
else {
char * tmp_answers[50];
int i = 0;
while (questions && *questions) {
tmp_answers[i] = get_auto_value(*questions_auto);
log_message("AUTOMATIC: question %s answers %s because of param %s", *questions, tmp_answers[i], *questions_auto);
i++;
questions++;
questions_auto++;
}
*answers = memdup(tmp_answers, sizeof(char *) * i);
return RETURN_OK;
}
}

32
automatic.h Normal file
View File

@ -0,0 +1,32 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* This is supposed to replace the redhat "kickstart", by name but
* also by design (no code pollution).
*
*/
#ifndef _AUTOMATIC_H_
#define _AUTOMATIC_H_
#include "stage1.h"
void grab_automatic_params(char * line);
enum return_type ask_from_list_auto(char *msg, char ** elems, char ** choice, char * auto_param, char ** elems_auto);
enum return_type ask_from_list_comments_auto(char *msg, char ** elems, char ** elems_comments, char ** choice, char * auto_param, char ** elems_auto);
enum return_type ask_from_entries_auto(char *msg, char ** questions, char *** answers, int entry_size, char ** questions_auto, void (*callback_func)(char ** strings));
#endif

184
cdrom.c Normal file
View File

@ -0,0 +1,184 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/mount.h>
#include "stage1.h"
#include "frontend.h"
#include "modules.h"
#include "probing.h"
#include "log.h"
#include "mount.h"
#include "cdrom.h"
static int mount_that_cd_device(char * dev_name)
{
char device_fullname[50];
strcpy(device_fullname, "/dev/");
strcat(device_fullname, dev_name);
return my_mount(device_fullname, IMAGE_LOCATION, "iso9660", 0);
}
static int test_that_cd()
{
return access(IMAGE_LOCATION LIVE_LOCATION, R_OK);
}
static enum return_type try_with_device(char * dev_name, char * dev_model);
static enum return_type do_with_device(char * dev_name, char * dev_model)
{
if (test_that_cd()) {
enum return_type results;
umount(IMAGE_LOCATION);
results = ask_yes_no("That CDROM disc does not seem to be a " DISTRIB_NAME " Installation CDROM.\nRetry with another disc?");
if (results == RETURN_OK)
return try_with_device(dev_name, dev_model);
return results;
}
log_message("found a " DISTRIB_NAME " CDROM, good news!");
//if (!IS_SPECIAL_STAGE2 && ramdisk_possible())
if (!IS_LOWMEM && ramdisk_possible())
load_ramdisk(); /* we don't care about return code, we'll do it live if we failed */
if (IS_RESCUE) {
load_ramdisk();
umount(IMAGE_LOCATION);
}
method_name = strdup("cdrom");
return RETURN_OK;
}
static enum return_type try_with_device(char * dev_name, char * dev_model)
{
wait_message("Trying to access a CDROM disc (drive %s)", dev_model);
if (mount_that_cd_device(dev_name) == -1) {
enum return_type results;
char msg[500];
unset_param(MODE_AUTOMATIC); /* we are in a fallback mode */
remove_wait_message();
snprintf(msg, sizeof(msg), "I can't access a " DISTRIB_NAME " Installation disc in your CDROM drive (%s).\nRetry?", dev_model);
results = ask_yes_no(msg);
if (results == RETURN_OK)
return try_with_device(dev_name, dev_model);
return results;
}
remove_wait_message();
return do_with_device(dev_name, dev_model);
}
enum return_type cdrom_prepare(void)
{
char ** medias, ** ptr, ** medias_models;
char * choice;
int i, count = 0;
enum return_type results;
my_insmod("ide-cd", ANY_DRIVER_TYPE, NULL);
my_insmod("sr_mod", ANY_DRIVER_TYPE, NULL);
get_medias(CDROM, &medias, &medias_models);
ptr = medias;
while (ptr && *ptr) {
count++;
ptr++;
}
if (count == 0) {
stg1_error_message("No CDROM device found.");
i = ask_insmod(SCSI_ADAPTERS);
if (i == RETURN_BACK)
return RETURN_BACK;
return cdrom_prepare();
}
if (count == 1) {
results = try_with_device(*medias, *medias_models);
if (results == RETURN_OK)
return RETURN_OK;
i = ask_insmod(SCSI_ADAPTERS);
if (i == RETURN_BACK)
return RETURN_BACK;
return cdrom_prepare();
}
if (IS_AUTOMATIC) {
char ** model = medias_models;
ptr = medias;
while (ptr && *ptr) {
wait_message("Trying to access " DISTRIB_NAME " CDROM disc (drive %s)", *model);
if (mount_that_cd_device(*ptr) != -1) {
if (!test_that_cd()) {
remove_wait_message();
return do_with_device(*ptr, *model);
}
else
umount(IMAGE_LOCATION);
}
remove_wait_message();
ptr++;
model++;
}
unset_param(MODE_AUTOMATIC);
return cdrom_prepare();
}
else {
results = ask_from_list_comments("Please choose the CDROM drive to use for the installation.", medias, medias_models, &choice);
if (results == RETURN_OK) {
char ** model = medias_models;
ptr = medias;
while (ptr && *ptr && model && *model) {
if (!strcmp(*ptr, choice))
break;
ptr++;
model++;
}
results = try_with_device(choice, *model);
} else
return results;
}
if (results == RETURN_OK)
return RETURN_OK;
if (results == RETURN_BACK)
return cdrom_prepare();
i = ask_insmod(SCSI_ADAPTERS);
if (i == RETURN_BACK)
return RETURN_BACK;
return cdrom_prepare();
}

29
cdrom.h Normal file
View File

@ -0,0 +1,29 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#ifndef _CDROM_H_
#define _CDROM_H_
#include "stage1.h"
enum return_type cdrom_prepare(void);
#endif

48
config-stage1.h Normal file
View File

@ -0,0 +1,48 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
#ifndef _CONFIG_STAGE1_H_
#define _CONFIG_STAGE1_H_
#define _GNU_SOURCE 1
/* If we have more than that amount of memory (in Mbytes), we assume we can load the second stage as a ramdisk */
#define MEM_LIMIT_RAMDISK 80
/* If we have more than that amount of memory (in Mbytes), we assume we can load the rescue as a ramdisk */
#define MEM_LIMIT_RESCUE 56
// #define DISTRIB_NAME "ALT Linux Junior 2.2"
#define RAMDISK_COMPRESSION_RATIO 1.95
#define LIVE_LOCATION "/ALTLinux/mdkinst/"
#define RAMDISK_LOCATION "/ALTLinux/base/"
#define IMAGE_LOCATION "/tmp/image"
#define STAGE2_LOCATION "/tmp/stage2"
/* user-definable (in Makefile): DISABLE_NETWORK, DISABLE_DISK, DISABLE_CDROM, DISABLE_PCMCIA */
/* some factorizing for disabling more features */
#ifdef DISABLE_DISK
#ifdef DISABLE_CDROM
#define DISABLE_MEDIAS
#endif
#endif
#endif

48
config-stage1.h-master Normal file
View File

@ -0,0 +1,48 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
#ifndef _CONFIG_STAGE1_H_
#define _CONFIG_STAGE1_H_
#define _GNU_SOURCE 1
/* If we have more than that amount of memory (in Mbytes), we assume we can load the second stage as a ramdisk */
#define MEM_LIMIT_RAMDISK 52
/* If we have more than that amount of memory (in Mbytes), we assume we can load the rescue as a ramdisk */
#define MEM_LIMIT_RESCUE 40
#define DISTRIB_NAME "ALT Linux Junior"
#define RAMDISK_COMPRESSION_RATIO 1.95
#define LIVE_LOCATION "/Mandrake/mdkinst/"
#define RAMDISK_LOCATION "/Mandrake/base/"
#define IMAGE_LOCATION "/tmp/image"
#define STAGE2_LOCATION "/tmp/stage2"
/* user-definable (in Makefile): DISABLE_NETWORK, DISABLE_DISK, DISABLE_CDROM, DISABLE_PCMCIA */
/* some factorizing for disabling more features */
#ifdef DISABLE_DISK
#ifdef DISABLE_CDROM
#define DISABLE_MEDIAS
#endif
#endif
#endif

615
dhcp.c Normal file
View File

@ -0,0 +1,615 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
/*
* Portions from GRUB -- GRand Unified Bootloader
* Copyright (C) 2000 Free Software Foundation, Inc.
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
// #include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <net/route.h>
#include <errno.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <sys/time.h>
#include <time.h>
#include <fcntl.h>
#include <sys/poll.h>
#include "stage1.h"
#include "log.h"
#include "network.h"
#include "frontend.h"
#include "dhcp.h"
typedef int bp_int32;
typedef short bp_int16;
#define BOOTP_OPTION_NETMASK 1
#define BOOTP_OPTION_GATEWAY 3
#define BOOTP_OPTION_DNS 6
#define BOOTP_OPTION_HOSTNAME 12
#define BOOTP_OPTION_DOMAIN 15
#define BOOTP_OPTION_BROADCAST 28
#define DHCP_OPTION_REQADDR 50
#define DHCP_OPTION_LEASE 51
#define DHCP_OPTION_TYPE 53
#define DHCP_OPTION_SERVER 54
#define DHCP_OPTION_OPTIONREQ 55
#define DHCP_OPTION_MAXSIZE 57
#define BOOTP_CLIENT_PORT 68
#define BOOTP_SERVER_PORT 67
#define BOOTP_OPCODE_REQUEST 1
#define BOOTP_OPCODE_REPLY 2
#define DHCP_TYPE_DISCOVER 1
#define DHCP_TYPE_OFFER 2
#define DHCP_TYPE_REQUEST 3
#define DHCP_TYPE_ACK 5
#define DHCP_TYPE_RELEASE 7
#define BOOTP_VENDOR_LENGTH 64
#define DHCP_VENDOR_LENGTH 340
struct bootp_request {
char opcode;
char hw;
char hwlength;
char hopcount;
bp_int32 id;
bp_int16 secs;
bp_int16 flags;
bp_int32 ciaddr, yiaddr, server_ip, bootp_gw_ip;
char hwaddr[16];
char servername[64];
char bootfile[128];
char vendor[DHCP_VENDOR_LENGTH];
} ;
static const char vendor_cookie[] = { 99, 130, 83, 99, 255 };
static unsigned int verify_checksum(void * buf2, int length2)
{
unsigned int csum = 0;
unsigned short * sp;
for (sp = (unsigned short *) buf2; length2 > 0; (length2 -= 2), sp++)
csum += *sp;
while (csum >> 16)
csum = (csum & 0xffff) + (csum >> 16);
return (csum == 0xffff);
}
static int initial_setup_interface(char * device, int s) {
struct sockaddr_in * addrp;
struct ifreq req;
struct rtentry route;
int true = 1;
addrp = (struct sockaddr_in *) &req.ifr_addr;
strcpy(req.ifr_name, device);
addrp->sin_family = AF_INET;
addrp->sin_port = 0;
memset(&addrp->sin_addr, 0, sizeof(addrp->sin_addr));
req.ifr_flags = 0; /* take it down */
if (ioctl(s, SIOCSIFFLAGS, &req)) {
log_perror("SIOCSIFFLAGS (downing)");
return -1;
}
addrp->sin_family = AF_INET;
addrp->sin_addr.s_addr = htonl(0);
if (ioctl(s, SIOCSIFADDR, &req)) {
log_perror("SIOCSIFADDR");
return -1;
}
req.ifr_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;
if (ioctl(s, SIOCSIFFLAGS, &req)) {
log_perror("SIOCSIFFLAGS (upping)");
return -1;
}
memset(&route, 0, sizeof(route));
memcpy(&route.rt_gateway, addrp, sizeof(*addrp));
addrp->sin_family = AF_INET;
addrp->sin_port = 0;
addrp->sin_addr.s_addr = INADDR_ANY;
memcpy(&route.rt_dst, addrp, sizeof(*addrp));
memcpy(&route.rt_genmask, addrp, sizeof(*addrp));
route.rt_dev = device;
route.rt_flags = RTF_UP;
route.rt_metric = 0;
if (ioctl(s, SIOCADDRT, &route)) {
if (errno != EEXIST) {
close(s);
log_perror("SIOCADDRT");
return -1;
}
}
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &true, sizeof(true))) {
close(s);
log_perror("setsockopt");
return -1;
}
/* I need to sleep a bit in order for kernel to finish init of the
network device; this would allow to not send further multiple
dhcp requests when only one is needed. */
wait_message("Bringing up networking...");
sleep(2);
remove_wait_message();
return 0;
}
void set_missing_ip_info(struct interface_info * intf)
{
bp_int32 ipNum = *((bp_int32 *) &intf->ip);
bp_int32 nmNum;
if (intf->netmask.s_addr == 0)
inet_aton(guess_netmask(inet_ntoa(intf->ip)), &intf->netmask);
nmNum = *((bp_int32 *) &intf->netmask);
if (intf->broadcast.s_addr == 0)
*((bp_int32 *) &intf->broadcast) = (ipNum & nmNum) | ~(nmNum);
if (intf->network.s_addr == 0)
*((bp_int32 *) &intf->network) = ipNum & nmNum;
}
static void parse_reply(struct bootp_request * breq, struct interface_info * intf)
{
unsigned char * chptr;
unsigned char option, length;
memcpy(&intf->ip, &breq->yiaddr, 4);
chptr = breq->vendor;
chptr += 4;
while (*chptr != 0xFF && (void *) chptr < (void *) breq->vendor + DHCP_VENDOR_LENGTH) {
char tmp_str[500];
option = *chptr++;
if (!option)
continue;
length = *chptr++;
switch (option) {
case BOOTP_OPTION_DNS:
memcpy(&dns_server, chptr, sizeof(dns_server));
log_message("got dns %s", inet_ntoa(dns_server));
if (length >= sizeof(dns_server)*2) {
memcpy(&dns_server2, chptr+sizeof(dns_server), sizeof(dns_server2));
log_message("got dns2 %s", inet_ntoa(dns_server2));
}
break;
case BOOTP_OPTION_NETMASK:
memcpy(&intf->netmask, chptr, sizeof(intf->netmask));
log_message("got netmask %s", inet_ntoa(intf->netmask));
break;
case BOOTP_OPTION_DOMAIN:
memcpy(tmp_str, chptr, length);
tmp_str[length] = '\0';
domain = strdup(tmp_str);
log_message("got domain %s", domain);
break;
case BOOTP_OPTION_BROADCAST:
memcpy(&intf->broadcast, chptr, sizeof(intf->broadcast));
log_message("got broadcast %s", inet_ntoa(intf->broadcast));
break;
case BOOTP_OPTION_GATEWAY:
memcpy(&gateway, chptr, sizeof(gateway));
log_message("got gateway %s", inet_ntoa(gateway));
break;
case BOOTP_OPTION_HOSTNAME:
memcpy(tmp_str, chptr, length);
tmp_str[length] = '\0';
hostname = strdup(tmp_str);
log_message("got hostname %s", hostname);
break;
}
chptr += length;
}
set_missing_ip_info(intf);
}
static void init_vendor_codes(struct bootp_request * breq) {
memcpy(breq->vendor, vendor_cookie, sizeof(vendor_cookie));
}
static char gen_hwaddr[16];
static int prepare_request(struct bootp_request * breq, int sock, char * device)
{
struct ifreq req;
memset(breq, 0, sizeof(*breq));
breq->opcode = BOOTP_OPCODE_REQUEST;
strcpy(req.ifr_name, device);
if (ioctl(sock, SIOCGIFHWADDR, &req)) {
log_perror("SIOCSIFHWADDR");
return -1;
}
breq->hw = 1; /* ethernet */
breq->hwlength = IFHWADDRLEN;
memcpy(breq->hwaddr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
memcpy(gen_hwaddr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
breq->hopcount = 0;
init_vendor_codes(breq);
return 0;
}
static int get_vendor_code(struct bootp_request * bresp, unsigned char option, void * data)
{
unsigned char * chptr;
unsigned int length, theOption;
chptr = bresp->vendor + 4;
while (*chptr != 0xFF && *chptr != option) {
theOption = *chptr++;
if (!theOption)
continue;
length = *chptr++;
chptr += length;
}
if (*chptr++ == 0xff)
return 1;
length = *chptr++;
memcpy(data, chptr, length);
return 0;
}
static int currticks(void)
{
struct timeval tv;
long csecs;
int ticks_per_csec, ticks_per_usec;
/* Note: 18.2 ticks/sec. */
gettimeofday (&tv, 0);
csecs = tv.tv_sec / 10;
ticks_per_csec = csecs * 182;
ticks_per_usec = (((tv.tv_sec - csecs * 10) * 1000000 + tv.tv_usec) * 182 / 10000000);
return ticks_per_csec + ticks_per_usec;
}
#define BACKOFF_LIMIT 7
#define TICKS_PER_SEC 18
#define MAX_ARP_RETRIES 4
static void rfc951_sleep(int exp)
{
static long seed = 0;
long q;
unsigned long tmo;
if (exp > BACKOFF_LIMIT)
exp = BACKOFF_LIMIT;
if (!seed)
/* Initialize linear congruential generator. */
seed = (currticks () + *(long *) &gen_hwaddr + ((short *) gen_hwaddr)[2]);
/* Simplified version of the LCG given in Bruce Scheier's
"Applied Cryptography". */
q = seed / 53668;
if ((seed = 40014 * (seed - 53668 * q) - 12211 * q) < 0)
seed += 2147483563l;
/* Compute mask. */
for (tmo = 63; tmo <= 60 * TICKS_PER_SEC && --exp > 0; tmo = 2 * tmo + 1)
;
/* Sleep. */
log_message("<sleep>");
for (tmo = (tmo & seed) + currticks (); currticks () < tmo;);
}
static int handle_transaction(int s, struct bootp_request * breq, struct bootp_request * bresp,
struct sockaddr_in * server_addr, int dhcp_type)
{
struct pollfd polls;
int i, j;
int retry = 1;
int sin;
char eth_packet[ETH_FRAME_LEN];
struct iphdr * ip_hdr;
struct udphdr * udp_hdr;
unsigned char type;
unsigned long starttime;
int timeout = 1;
breq->id = starttime = currticks();
breq->secs = 0;
sin = socket(AF_PACKET, SOCK_DGRAM, ntohs(ETH_P_IP));
if (sin < 0) {
log_perror("af_packet socket");
return -1;
}
while (retry <= MAX_ARP_RETRIES) {
i = sizeof(*breq);
if (sendto(s, breq, i, 0, (struct sockaddr *) server_addr, sizeof(*server_addr)) != i) {
close(s);
log_perror("sendto");
return -1;
}
polls.fd = sin;
polls.events = POLLIN;
while (poll(&polls, 1, timeout*1000) == 1) {
if ((j = recv(sin, eth_packet, sizeof(eth_packet), 0)) == -1) {
log_perror("recv");
continue;
}
/* We need to do some basic sanity checking of the header */
if (j < (sizeof(*ip_hdr) + sizeof(*udp_hdr)))
continue;
ip_hdr = (void *) eth_packet;
if (!verify_checksum(ip_hdr, sizeof(*ip_hdr)))
continue;
if (ntohs(ip_hdr->tot_len) > j)
continue;
j = ntohs(ip_hdr->tot_len);
if (ip_hdr->protocol != IPPROTO_UDP)
continue;
udp_hdr = (void *) (eth_packet + sizeof(*ip_hdr));
if (ntohs(udp_hdr->source) != BOOTP_SERVER_PORT)
continue;
if (ntohs(udp_hdr->dest) != BOOTP_CLIENT_PORT)
continue;
/* Go on with this packet; it looks sane */
/* Originally copied sizeof (*bresp) - this is a security
problem due to a potential underflow of the source
buffer. Also, it trusted that the packet was properly
0xFF terminated, which is not true in the case of the
DHCP server on Cisco 800 series ISDN router. */
memset (bresp, 0xFF, sizeof (*bresp));
memcpy (bresp, (char *) udp_hdr + sizeof (*udp_hdr), j - sizeof (*ip_hdr) - sizeof (*udp_hdr));
/* sanity checks */
if (bresp->id != breq->id)
continue;
if (bresp->opcode != BOOTP_OPCODE_REPLY)
continue;
if (bresp->hwlength != breq->hwlength)
continue;
if (memcmp(bresp->hwaddr, breq->hwaddr, bresp->hwlength))
continue;
if (get_vendor_code(bresp, DHCP_OPTION_TYPE, &type) || type != dhcp_type)
continue;
if (memcmp(bresp->vendor, vendor_cookie, 4))
continue;
return 0;
}
rfc951_sleep(retry);
breq->secs = htons ((currticks () - starttime) / 20);
retry++;
timeout *= 2;
if (timeout > 5)
timeout = 5;
}
return -1;
}
static void add_vendor_code(struct bootp_request * breq, unsigned char option, unsigned char length, void * data)
{
unsigned char * chptr;
int theOption, theLength;
chptr = breq->vendor;
chptr += 4;
while (*chptr != 0xFF && *chptr != option) {
theOption = *chptr++;
if (!theOption) continue;
theLength = *chptr++;
chptr += theLength;
}
*chptr++ = option;
*chptr++ = length;
memcpy(chptr, data, length);
chptr[length] = 0xff;
}
enum return_type perform_dhcp(struct interface_info * intf)
{
int s, i;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
struct sockaddr_in broadcast_addr;
struct bootp_request breq, bresp;
unsigned char messageType;
unsigned int lease;
short aShort;
int num_options;
char requested_options[50];
if (strncmp(intf->device, "eth", 3)) {
stg1_error_message("DHCP available only for Ethernet networking.");
return RETURN_ERROR;
}
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
log_perror("socket");
return RETURN_ERROR;
}
if (initial_setup_interface(intf->device, s) != 0) {
close(s);
return RETURN_ERROR;
}
if (prepare_request(&breq, s, intf->device) != 0) {
close(s);
return RETURN_ERROR;
}
messageType = DHCP_TYPE_DISCOVER;
add_vendor_code(&breq, DHCP_OPTION_TYPE, 1, &messageType);
memset(&client_addr.sin_addr, 0, sizeof(&client_addr.sin_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(BOOTP_CLIENT_PORT); /* bootp client */
if (bind(s, (struct sockaddr *) &client_addr, sizeof(client_addr))) {
log_perror("bind");
return RETURN_ERROR;
}
broadcast_addr.sin_family = AF_INET;
broadcast_addr.sin_port = htons(BOOTP_SERVER_PORT); /* bootp server */
memset(&broadcast_addr.sin_addr, 0xff, sizeof(broadcast_addr.sin_addr)); /* broadcast */
log_message("DHCP: sending DISCOVER");
wait_message("Sending DHCP request...");
i = handle_transaction(s, &breq, &bresp, &broadcast_addr, DHCP_TYPE_OFFER);
remove_wait_message();
if (i != 0) {
stg1_error_message("No DHCP reply received.");
close(s);
return RETURN_ERROR;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(BOOTP_SERVER_PORT); /* bootp server */
if (get_vendor_code(&bresp, DHCP_OPTION_SERVER, &server_addr.sin_addr)) {
close(s);
log_message("DHCPOFFER didn't include server address");
return RETURN_ERROR;
}
init_vendor_codes(&breq);
messageType = DHCP_TYPE_REQUEST;
add_vendor_code(&breq, DHCP_OPTION_TYPE, 1, &messageType);
add_vendor_code(&breq, DHCP_OPTION_SERVER, 4, &server_addr.sin_addr);
add_vendor_code(&breq, DHCP_OPTION_REQADDR, 4, &bresp.yiaddr);
aShort = ntohs(sizeof(struct bootp_request));
add_vendor_code(&breq, DHCP_OPTION_MAXSIZE, 2, &aShort);
num_options = 0;
requested_options[num_options++] = BOOTP_OPTION_NETMASK;
requested_options[num_options++] = BOOTP_OPTION_GATEWAY;
requested_options[num_options++] = BOOTP_OPTION_DNS;
requested_options[num_options++] = BOOTP_OPTION_DOMAIN;
requested_options[num_options++] = BOOTP_OPTION_BROADCAST;
add_vendor_code(&breq, DHCP_OPTION_OPTIONREQ, num_options, requested_options);
/* request a lease of 1 hour */
i = htonl(60 * 60);
add_vendor_code(&breq, DHCP_OPTION_LEASE, 4, &i);
log_message("DHCP: sending REQUEST");
i = handle_transaction(s, &breq, &bresp, &broadcast_addr, DHCP_TYPE_ACK);
if (i != 0) {
close(s);
return RETURN_ERROR;
}
if (get_vendor_code(&bresp, DHCP_OPTION_LEASE, &lease)) {
log_message("failed to get lease time\n");
return RETURN_ERROR;
}
lease = ntohl(lease);
close(s);
intf->netmask.s_addr = 0;
intf->broadcast.s_addr = 0;
intf->network.s_addr = 0;
parse_reply(&bresp, intf);
return RETURN_OK;
}

34
dhcp.h Normal file
View File

@ -0,0 +1,34 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* View the homepage: http://us.mandrakesoft.com/~gc/html/stage1.html
*
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from GRUB -- GRand Unified Bootloader
* Copyright (C) 2000 Free Software Foundation, Inc.
*
* Itself based on etherboot-4.6.4 by Martin Renters.
*
*/
#ifndef _DHCP_H_
#define _DHCP_H_
#include "stage1.h"
#include "network.h"
enum return_type perform_dhcp(struct interface_info * intf);
#endif

342
disk.c Normal file
View File

@ -0,0 +1,342 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "stage1.h"
#include "frontend.h"
#include "modules.h"
#include "probing.h"
#include "log.h"
#include "mount.h"
#include "lomount.h"
#include "automatic.h"
#include "disk.h"
struct partition_detection_anchor {
off_t offset;
const char * anchor;
};
static int seek_and_compare(int fd, struct partition_detection_anchor anch)
{
char buf[500];
int count;
if (lseek(fd, anch.offset, SEEK_SET) == (off_t)-1) {
log_perror("seek failed");
return -1;
}
count = read(fd, buf, strlen(anch.anchor));
if (count != strlen(anch.anchor)) {
log_perror("read failed");
return -1;
}
buf[count] = '\0';
if (strcmp(anch.anchor, buf))
return 1;
return 0;
}
static const char * detect_partition_type(char * dev)
{
struct partition_detection_info {
const char * name;
struct partition_detection_anchor anchor0;
struct partition_detection_anchor anchor1;
struct partition_detection_anchor anchor2;
};
struct partition_detection_info partitions_signatures[] = {
{ "Linux Swap", { 4086, "SWAP-SPACE" }, { 0, NULL } },
{ "Linux Swap", { 4086, "SWAPSPACE2" }, { 0, NULL } },
{ "Ext2", { 0x438, "\x53\xEF" }, { 0, NULL } },
{ "ReiserFS", { 0x10034, "ReIsErFs" }, { 0, NULL } },
{ "ReiserFS", { 0x10034, "ReIsEr2Fs" }, { 0, NULL } },
{ "XFS", { 0, "XFSB" }, { 0x200, "XAGF" }, { 0x400, "XAGI" } },
{ "JFS", { 0x8000, "JFS1" }, { 0, NULL } },
{ "NTFS", { 0x1FE, "\x55\xAA" }, { 0x3, "NTFS" }, { 0, NULL } },
{ "FAT32", { 0x1FE, "\x55\xAA" }, { 0x52, "FAT32" }, { 0, NULL } },
{ "FAT", { 0x1FE, "\x55\xAA" }, { 0x36, "FAT" }, { 0, NULL } },
{ "Linux LVM", { 0, "HM\1\0" }, { 0, NULL }, { 0, NULL } }
};
int partitions_signatures_nb = sizeof(partitions_signatures) / sizeof(struct partition_detection_info);
int i;
int fd;
char device_fullname[50];
strcpy(device_fullname, "/dev/");
strcat(device_fullname, dev);
if (ensure_dev_exists(device_fullname))
return NULL;
log_message("guessing type of %s", device_fullname);
if ((fd = open(device_fullname, O_RDONLY, 0)) < 0) {
log_perror("open");
return NULL;
}
for (i=0; i<partitions_signatures_nb; i++) {
int results = seek_and_compare(fd, partitions_signatures[i].anchor0);
if (results == -1)
goto detect_partition_type_end;
if (results == 1)
continue;
if (!partitions_signatures[i].anchor1.anchor)
goto detect_partition_found_it;
results = seek_and_compare(fd, partitions_signatures[i].anchor1);
if (results == -1)
goto detect_partition_type_end;
if (results == 1)
continue;
if (!partitions_signatures[i].anchor2.anchor)
goto detect_partition_found_it;
results = seek_and_compare(fd, partitions_signatures[i].anchor2);
if (results == -1)
goto detect_partition_type_end;
if (results == 1)
continue;
detect_partition_found_it:
return partitions_signatures[i].name;
}
detect_partition_type_end:
close(fd);
return NULL;
}
static char * disk_extract_list_directory(char * direct)
{
char ** full = list_directory(direct);
char tmp[2000] = "";
int i;
for (i=0; i<5 ; i++) {
if (!full || !*full)
break;
strcat(tmp, *full);
strcat(tmp, "\n");
full++;
}
return strdup(tmp);
}
static enum return_type try_with_device(char *dev_name)
{
char * questions_location[] = { "Directory or ISO image", NULL };
char * questions_location_auto[] = { "directory", NULL };
static char ** answers_location = NULL;
char device_fullname[50];
char location_full[500];
char * disk_own_mount = "/tmp/hdimage";
int major, minor, blocks;
char name[100];
char buf[512];
FILE * f;
char * parts[50];
char * parts_comments[50];
struct stat statbuf;
int i = 0;
enum return_type results;
char * choice;
if (!(f = fopen("/proc/partitions", "rb")) || !fgets(buf, sizeof(buf), f) || !fgets(buf, sizeof(buf), f)) {
log_perror(dev_name);
stg1_error_message("Could not read partitions information.");
return RETURN_ERROR;
}
while (fgets(buf, sizeof(buf), f)) {
bzero(name, sizeof(name));
sscanf(buf, " %d %d %d %s", &major, &minor, &blocks, name);
if ((strstr(name, dev_name) == name) && (blocks > 1) && (name[strlen(dev_name)] != '\0')) {
const char * partition_type = detect_partition_type(name);
parts[i] = strdup(name);
parts_comments[i] = (char *) malloc(sizeof(char) * 100);
sprintf(parts_comments[i], "size: %d Mbytes", blocks >> 10);
if (partition_type) {
strcat(parts_comments[i], ", type: ");
strcat(parts_comments[i], partition_type);
}
i++;
}
}
parts[i] = NULL;
fclose(f);
if (parts[0] == NULL) {
stg1_error_message("No partitions found.");
return RETURN_ERROR;
}
results = ask_from_list_comments_auto("Please choose the partition where is copied the " DISTRIB_NAME " Distribution.",
parts, parts_comments, &choice, "partition", parts);
if (results != RETURN_OK)
return results;
strcpy(device_fullname, "/dev/");
strcat(device_fullname, choice);
if (my_mount(device_fullname, disk_own_mount, "ext2", 0) == -1 &&
my_mount(device_fullname, disk_own_mount, "vfat", 0) == -1 &&
my_mount(device_fullname, disk_own_mount, "reiserfs", 0) == -1) {
stg1_error_message("I can't find a valid filesystem (tried: ext2, vfat, reiserfs).");
return try_with_device(dev_name);
}
if (ask_from_entries_auto("Please enter the directory (or ISO image file) containing the " DISTRIB_NAME " Distribution.",
questions_location, &answers_location, 24, questions_location_auto, NULL) != RETURN_OK) {
umount(disk_own_mount);
return try_with_device(dev_name);
}
strcpy(location_full, disk_own_mount);
strcat(location_full, "/");
strcat(location_full, answers_location[0]);
if (access(location_full, R_OK)) {
stg1_error_message("Directory or ISO image file could not be found on partition.\n"
"Here's a short extract of the files in the root of the partition:\n"
"%s", disk_extract_list_directory(disk_own_mount));
umount(disk_own_mount);
return try_with_device(dev_name);
}
unlink(IMAGE_LOCATION);
if (!stat(location_full, &statbuf) && !S_ISDIR(statbuf.st_mode)) {
log_message("%s exists and is not a directory, assuming this is an ISO image", location_full);
if (lomount(location_full, IMAGE_LOCATION)) {
stg1_error_message("Could not mount file %s as an ISO image of the " DISTRIB_NAME " Distribution.", answers_location[0]);
umount(disk_own_mount);
return try_with_device(dev_name);
}
} else
symlink(location_full, IMAGE_LOCATION);
if (IS_SPECIAL_STAGE2 || ramdisk_possible()) {
/* RAMDISK install */
if (access(IMAGE_LOCATION RAMDISK_LOCATION, R_OK)) {
stg1_error_message("I can't find the " DISTRIB_NAME " Distribution in the specified directory. "
"(I need the subdirectory " RAMDISK_LOCATION ")\n"
"Here's a short extract of the files in the directory:\n"
"%s", disk_extract_list_directory(IMAGE_LOCATION));
loumount();
umount(disk_own_mount);
return try_with_device(dev_name);
}
if (load_ramdisk() != RETURN_OK) {
stg1_error_message("Could not load program into memory.");
loumount();
umount(disk_own_mount);
return try_with_device(dev_name);
}
} else {
/* LIVE install */
char p;
if (access(IMAGE_LOCATION LIVE_LOCATION, R_OK)) {
stg1_error_message("I can't find the " DISTRIB_NAME " Distribution in the specified directory. "
"(I need the subdirectory " LIVE_LOCATION ")\n"
"Here's a short extract of the files in the directory:\n"
"%s", disk_extract_list_directory(IMAGE_LOCATION));
loumount();
umount(disk_own_mount);
return try_with_device(dev_name);
}
if (readlink(IMAGE_LOCATION LIVE_LOCATION "/usr/bin/runinstall2", &p, 1) != 1) {
stg1_error_message("The " DISTRIB_NAME " Distribution seems to be copied on a Windows partition. "
"You need more memory to perform an installation from a Windows partition. "
"Another solution if to copy the " DISTRIB_NAME " Distribution on a Linux partition.");
loumount();
umount(disk_own_mount);
return try_with_device(dev_name);
}
log_message("found the " DISTRIB_NAME " Installation, good news!");
}
if (IS_RESCUE) {
loumount();
umount(disk_own_mount);
}
method_name = strdup("disk");
return RETURN_OK;
}
enum return_type disk_prepare(void)
{
char ** medias, ** ptr, ** medias_models;
char * choice;
int i, count = 0;
enum return_type results;
my_insmod("sd_mod", ANY_DRIVER_TYPE, NULL);
get_medias(DISK, &medias, &medias_models);
ptr = medias;
while (ptr && *ptr) {
count++;
ptr++;
}
if (count == 0) {
stg1_error_message("No DISK drive found.");
i = ask_insmod(SCSI_ADAPTERS);
if (i == RETURN_BACK)
return RETURN_BACK;
return disk_prepare();
}
if (count == 1) {
results = try_with_device(*medias);
if (results == RETURN_OK)
return RETURN_OK;
i = ask_insmod(SCSI_ADAPTERS);
if (i == RETURN_BACK)
return RETURN_BACK;
return disk_prepare();
}
results = ask_from_list_comments_auto("Please choose the DISK drive on which you copied the " DISTRIB_NAME " Distribution.",
medias, medias_models, &choice, "disk", medias);
if (results != RETURN_OK)
return results;
results = try_with_device(choice);
if (results == RETURN_OK)
return RETURN_OK;
i = ask_insmod(SCSI_ADAPTERS);
if (i == RETURN_BACK)
return RETURN_BACK;
return disk_prepare();
}

27
disk.h Normal file
View File

@ -0,0 +1,27 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#ifndef _DISK_H_
#define _DISK_H_
enum return_type disk_prepare(void);
#endif

213
dns.c Normal file
View File

@ -0,0 +1,213 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#include <stdlib.h>
// dietlibc can do hostname lookup, whereas glibc can't when linked statically :-(
#ifdef __LIBC_DIETLIBC__
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <netdb.h>
// #include <sys/socket.h>
#include "network.h"
#include "log.h"
#include "dns.h"
int mygethostbyname(char * name, struct in_addr * addr)
{
struct hostent * h = gethostbyname(name);
if (!h) {
if (domain) {
// gethostbyname from dietlibc doesn't support domain handling
char fully_qualified[500];
sprintf(fully_qualified, "%s.%s", name, domain);
h = gethostbyname(fully_qualified);
if (!h) {
log_message("unknown host %s", name);
return -1;
}
} else
return -1;
}
if (h->h_addr_list && (h->h_addr_list)[0]) {
memcpy(addr, (h->h_addr_list)[0], sizeof(*addr));
log_message("is-at: %s", inet_ntoa(*addr));
return 0;
}
return -1;
}
char * mygethostbyaddr(char * ipnum)
{
struct in_addr in;
struct hostent * host;
if (!inet_aton(ipnum, &in))
return NULL;
host = gethostbyaddr(&in, strlen((void *) &in), AF_INET);
if (host && host->h_name)
return host->h_name;
return NULL;
}
#else // __LIBC_DIETLIBC__
#include <alloca.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <resolv.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include "log.h"
#include "dns.h"
/* This is dumb, but glibc doesn't like to do hostname lookups w/o libc.so */
union dns_response {
HEADER hdr;
u_char buf[PACKETSZ];
} ;
static int do_query(char * query, int queryType, char ** domainName, struct in_addr * ipNum)
{
int len, ancount, type;
u_char * data, * end;
char name[MAXDNAME];
union dns_response response;
#ifdef __sparc__
/* from jj: */
/* We have to wait till ethernet negotiation is done */
_res.retry = 3;
#else
_res.retry = 2;
#endif
len = res_search(query, C_IN, queryType, (void *) &response, sizeof(response));
if (len <= 0)
return -1;
if (ntohs(response.hdr.rcode) != NOERROR)
return -1;
ancount = ntohs(response.hdr.ancount);
if (ancount < 1)
return -1;
data = response.buf + sizeof(HEADER);
end = response.buf + len;
/* skip the question */
data += dn_skipname(data, end) + QFIXEDSZ;
/* parse the answer(s) */
while (--ancount >= 0 && data < end) {
/* skip the domain name portion of the RR record */
data += dn_skipname(data, end);
/* get RR information */
GETSHORT(type, data);
data += INT16SZ; /* skipp class */
data += INT32SZ; /* skipp TTL */
GETSHORT(len, data);
if (type == T_PTR) {
/* we got a pointer */
len = dn_expand(response.buf, end, data, name, sizeof(name));
if (len <= 0) return -1;
if (queryType == T_PTR && domainName) {
/* we wanted a pointer */
*domainName = malloc(strlen(name) + 1);
strcpy(*domainName, name);
return 0;
}
} else if (type == T_A) {
/* we got an address */
if (queryType == T_A && ipNum) {
/* we wanted an address */
memcpy(ipNum, data, sizeof(*ipNum));
return 0;
}
}
/* move ahead to next RR */
data += len;
}
return -1;
}
char * mygethostbyaddr(char * ipnum) {
int rc;
char * result;
char * strbuf;
char * chptr;
char * splits[4];
int i;
_res.retry = 1;
strbuf = alloca(strlen(ipnum) + 1);
strcpy(strbuf, ipnum);
ipnum = alloca(strlen(strbuf) + 20);
for (i = 0; i < 4; i++) {
chptr = strbuf;
while (*chptr && *chptr != '.')
chptr++;
*chptr = '\0';
if (chptr - strbuf > 3) return NULL;
splits[i] = strbuf;
strbuf = chptr + 1;
}
sprintf(ipnum, "%s.%s.%s.%s.in-addr.arpa", splits[3], splits[2], splits[1], splits[0]);
rc = do_query(ipnum, T_PTR, &result, NULL);
if (rc)
return NULL;
else
return result;
}
int mygethostbyname(char * name, struct in_addr * addr) {
int rc = do_query(name, T_A, NULL, addr);
if (!rc)
log_message("is-at %s", inet_ntoa(*addr));
return rc;
}
#endif

30
dns.h Normal file
View File

@ -0,0 +1,30 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#ifndef H_DNS
#define H_DNS
#include <netinet/in.h>
int mygethostbyname(char * name, struct in_addr * addr);
char * mygethostbyaddr(char * ipnum);
#endif

31
doc/HACKING Normal file
View File

@ -0,0 +1,31 @@
If you have to boot pretty often, you'll appreciate to speed the things up
a little.
Here's what we use: the GRUB feature to boot from the network using the
DHCP protocol and the TFTP protocol.
Here's the "menu.lst" to do that:
-=-=--
timeout 0
title linux
dhcp
tftpserver 192.168.1.17
kernel (nd)/tftpboot/gc/vmlinuz ramdisk=32000 vga=788
initrd (nd)/tftpboot/gc/network.rdz
-=-=--
The option "tftpserver" is used to override the tftpserver address given
as an answer by the DHCP server. That way, you'll not need to bother your
system administrator to modify his dhcp server configuration.
The directory /tftpboot seems to be the only one defaultly accepted by the
server, and its subdirs.
Of course, your GRUB needs to be compiled with the specific code for your
network card; use ./configure --help in the GRUB build dir for more infos.

185
doc/README Normal file
View File

@ -0,0 +1,185 @@
-------------------------------------------------------
* Stage1 of the Mandrake Linux installation program *
-------------------------------------------------------
[ Author ]
Guillaume Cottenceau (gc@mandrakesoft.com)
[ Copyright ]
Copyright 2000 MandrakeSoft
Partially inspired by Redhat stuff (install from 5.x and 7.x) copyright
Red Hat Software, and Debian stuff (boot-floppies) copyright by their
respective holders.
[ Licence ]
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 of the License, 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*** WARNING! ***
This General Public License does not permit incorporating any part
of this program as a library into proprietary programs.
[ Online ]
http://us.mandrakesoft.com/~gc/html/stage1.html
[ Purpose ]
This code will take the control of the computer after that Linux
kernel booted properly, and will try to run the main installer
(also known as "stage 2") from a series of different media
including harddrive, cdrom, and network.
Use the source, Luke.
-=-=-- Okay, now, more details --=-=-
[ Installing Mandrake Linux ]
Per default, just insert your Mandrake Linux Installation CD into your
CDROM tray, be sure your system BIOS is configured to boot on your CDROM,
and that's all.
If you have multiple CDROM drives and the installer can't autodetect in
which CDROM drive is the disc, it may ask you to choose the correct drive,
between your CDROM drives.
Also, if you want to install from an SCSI CDROM, the installer should
detect your SCSI adapter; if it fails you may have to select the right
driver and/or supply additional parameters.
[ Position of the problem ]
The need for alternate installation methods come with more specific
hardware configuration and/or need for frequent updates of the Installer
software.
All of these methods will require to use a special boot disk. The method
is to download it and then to copy it "physically" to a floppy with the
command:
# dd if=<boot-disk> of=/dev/fd0
Our boot disks are called "cdrom.img", "network.img", etc.
[ Installation from CDROM ]
The first situation you may encounter is an old BIOS which does not permit
you to boot from your CDROM drive.
In that case, you'll need to use the "cdrom.img" image file. The steps are
the same as with CDROM boot, and everything should be automatic.
[ Installation from DISK ]
If you like trying occasionnally our development version, the Cooker, one
of the easiest way is to grab a local copy of the Distribution on one of
your local hard drives, and to install from that location.
At present time, you can install from IDE or SCSI drives, from Linux
(ext2), Windows (vfat) or Reiserfs partition.
In that case, you'll need to use the "hd.img" image file. The dialogs will
ask you to choose the DISK drive to use to install from, then the
partition on which you copied the Distribution, then the location
(directory) in which you copied the Distribution.
[ Installation from NETWORK ]
For convenience, you can also install from a NFS volume, from a FTP
server, or from a HTTP server. NFS installs are maybe the fastest
and most convenient possible, so if you need to do frequent and/or
multiple installs, you may like this option.
In that case, you'll need to use the "network.img" image file. If you have
PCI network card(s), you'll probably have to only setup your network
options. If not, you'll have to choose the appropriate driver(s) and/or
optional parameters. Supported network configurations include static IP
allocation and DHCP automatic configuration.
[ Installation from PCMCIA ]
If you want to perform an installation on your laptop that is not based on
local IDE CDROM or DISK, nor on built-in network card, but on PCMCIA
extension (probably a network adapter or CDROM drive), you'll need the
"pcmcia.img" image file.
PCMCIA services should automatically start and be transparent to you.
Then, you'll follow the instructions according to your preferred
installation method.
[ Monitoring a stage1 session ]
Linux supports virtual consoles. You can switch between them by issueing
Ctrl+Alt+Fx key, in which 'x' is the number of the console. Here's console
occupancy during stage1.
(#1) The user-interface of the stage1 is on the first console. In case of
newt interaction, it's provided with a neat blue and black color scheme,
and nice widgets. In case of stdio interaction (cdrom and disk installs),
it's more basic but still usable :-).
(#2) A shell is provided on second console in some cases (you need to
compile it with -DSPAWN_SHELL and you need to provide a valid shell in the
initrd) and of course it's not in, in image files of Mandrake Linux
releases because it's too much diskspace.
(#3) The log is printed out on the third console. This is the location
where you can find most valuable information, prefixed by a '*'. See
"log.h" for calls that print things out to the log.
(#4) The kernel messages are printed on the fourth console. There is a
process forked very early in the init (the program before the stage1)
which monitors /proc/kmsg for new kernel messages. Also, syslog stuff (the
logs commited by the programs) should appear on the /dev/log Unix socket,
this is also printed on this console.
(#5) Former place for the stderr of insmod calls. It's not used anymore.
(#6) Place where a trivial interactive communication with the stage1 is
set up if the parameter -DSPAWN_INTERACTIVE is compiled in. Basically, you
can set switches such as "expert" and "rescue" on the fly with this
feature. It's implemented with a fork and a Unix pipe.
[ Rescueing a system ]
Since Mandrake Linux 7.1, we provide a rescue system through each of the
previously described methods. You don't need a special "rescue.img" file.
Just hit "F1" at boot time, type in "rescue", and follow the first steps
of the installation according to the method you chose (choose
disks/partitions for disk method, network parameters for network method,
etc). Then, you'll end up with a workable system, very useful to rescue a
damaged system, or do other basic actions.

80
doc/TECH-INFOS Normal file
View File

@ -0,0 +1,80 @@
| (*) Automatic install
\----------------------
This feature is used to replace redhat kickstart. It uses the kernel
parameter "automatic" with keywords separated with commas and colons, on
the following genres:
automatic=method:nfs,network:static,ip:192.168.1.24,server:192.168.1.7,directory:/stable/i586
automatic=method:ftp,network:dhcp,server:ftp.ciril.fr,directory:/pub/linux/mandrake-devel/cooker
automatic=method:ftp,network:dhcp,server:companyserver,directory:/mdkinst,user:XXX,pass:XXX
automatic=method:ftp,interface:eth1,network:dhcp,...
automatic=method:ftp,network:adsl,adsluser:XXX,adslpass:XXX,...
automatic=method:cdrom
automatic=method:disk,disk:hdb,partition:hdb7
The keywords correspond to each "virtual" question answered automatically,
either from a list or from a free field.
Keywords are:
`method' <- (nfs,ftp,http,cdrom,disk)
if nfs/ftp/http:
`network' <- (static,dhcp,adsl)
if multiple interfaces detected:
`interface' <- (list-of-detected-interfaces)
fi
if static:
`ip', `dns', `gateway', `netmask' (free fields)
elsif adsl:
`adsluser', `adslpass' (free field)
fi
if resolving fails:
`hostname', `domain' (free fields)
fi
`server', `directory' (free fields)
if ftp:
`user', `pass' (free fields)
fi
fi
if disk:
`disk' <- (list-of-detected-disks)
`partition' <- (list-of-detected-partitions)
`directory' (free fields)
fi

71
doc/UPDATEMODULES Normal file
View File

@ -0,0 +1,71 @@
This is the documentation for the "Update Modules" (Update Drivers)
feature.
This feature aims to propose new modules or replacement modules for the
install. This is useful when there is a firmware update for a given
driver, an additional driver needed for something, etc.
You must use a floppy disk with e2fs filesystem (NOT vfat/windows
formatted). Use "mke2fs /dev/fd0" on your own box to format a floppy with
e2fs filesystem.
This disk may contain a number of kernel modules on the root (e.g. not in
a subdirectory); some of them may replace existing modules, some of them
may be added. This disk must contain a special file, named "to_load", on
the root (not in a subdirectory). This file will contain a series of
module names, with optional module options; the program will try to load
all these modules one after another, using file on the floppy if present,
else using file within standard module repository ("marfile" on the boot
floppy). It can contain comments, these are strictly defined by the
presence of a hash (#) character on row 0 of any line. Beware, on the
first line of the line, a comment is mandatory (there is a bug somewhere).
Here's a typical scenario:
1. Boot the floppy (or cdrom) with the option "updatemodules"
(you may do that by pressing F1 then entering "linux updatemodules")
2. At the very beginning of the User Interface, you are asked to insert
the Update Modules disk. Insert the Update Modules disk and press
Enter.
--=----=----=----=----=----=----=----=----=--
Our example disk contains:
[root@obiwan mnt]# ll floppy/
total 77
drwxr-xr-x 2 root root 12288 Jul 26 12:02 lost+found/
-rw-r--r-- 1 root root 9051 Jul 26 12:43 msdos.o
-rw-r--r-- 1 root root 13660 Jul 26 12:04 ppa.o
-rw-r--r-- 1 root root 54 Jul 26 12:46 to_load
-rw-r--r-- 1 root root 32108 Jul 26 12:04 uhci.o
-rw-r--r-- 1 root root 6572 Jul 26 12:04 wacom.o
[root@obiwan mnt]# cat floppy/to_load
# Update Drivers description file
3c59x
# fat is a dep for msdos
fat
# updated msdos (handling of 9+4 filenames)
msdos
ppa
[root@obiwan mnt]#
--=----=----=----=----=----=----=----=----=--
3. The program reads the special file "to_load" and processes the files.
a- 3c59x loaded from the marfile on the boot floppy
b- fat loaded from the marfile on the boot floppy
c- msdos loaded from the update modules floppy
d- ppa loaded from the update modules floppy
Beware, the dependencies are not handled automatically in the case of load
from the update modules floppy, that's why on our example we need to load
"fat" from the standard modules before "msdos" from the update floppy.

50
doc/WHY-DIETLIBC Normal file
View File

@ -0,0 +1,50 @@
(the dietlibc is a replacement for the glibc, which aim is to produce
smaller statically linked binaries)
The use for dietlibc in the stage1 was clear because currently used
install process on x86 is from a 1.44 Mbytes floppy. On this floppy we
need to fit the kernel, modules (scsi and network access), and the code to
do the basic things to load the stage2. The only part on which we could
progress was the code.
As always, figures demonstrate evidences. Here are the size of the
binaries used for the cdrom, disk, network and full floppy installs, using
newt as the UI library:
- with glibc
-rwxr-xr-x 1 gc gc 569448 May 15 15:29 stage1-cdrom
-rwxr-xr-x 1 gc gc 572264 May 15 15:29 stage1-disk
-rwxr-xr-x 1 gc gc 624712 May 15 15:30 stage1-network
-rwxr-xr-x 1 gc gc 720360 May 15 15:29 stage1-full
- with dietlibc
-rwxr-xr-x 1 gc gc 169332 May 15 14:26 stage1-cdrom
-rwxr-xr-x 1 gc gc 172180 May 15 14:26 stage1-disk
-rwxr-xr-x 1 gc gc 198612 May 15 14:26 stage1-network
-rwxr-xr-x 1 gc gc 251764 May 15 14:26 stage1-full
The `stage1-full' binary has code for many things, most notably: data
decrunching (bzlib), archive extraction (in-house format), module loading
(insmod from busybox), PCI detection, ide and scsi handling,
cdrom/disk/loopback mounting, DHCP client negociation (redhat+grub), NFS
mounting (util-linux), FTP and HTTP transmission (redhat), pcmcia
initializing (pcmcia-cs), UI interaction (slang/newt); with use of the
dietlibc, the binary is only 250 kbytes!
Due to the modular coding, it is also possible to choose to not use
slang/newt as the UI, but a stdio-only UI. In that case, the binaries get
even smaller:
-rwxr-xr-x 1 gc gc 104500 May 15 15:46 stage1-cdrom*
-rwxr-xr-x 1 gc gc 107348 May 15 15:46 stage1-disk*
-rwxr-xr-x 1 gc gc 133972 May 15 15:47 stage1-network*
-rwxr-xr-x 1 gc gc 187348 May 15 15:46 stage1-full*
gc [Tue May 15 15:58:34 2001]

View File

@ -0,0 +1,69 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Using high-level UI.
*
* These functions are frontend-independant: your program won't know each
* `frontend' (e.g. each way to grab user input) will be used.
*
* Then you may link your binary against any `frontend' that implement all
* these functions (and possibly necessary libraries).
*/
#ifndef _FRONTEND_H_
#define _FRONTEND_H_
/* this must be called before anything else */
void init_frontend(void);
/* this must be called before exit of program */
void finish_frontend(void);
void info_message(char *msg, ...) __attribute__ ((format (printf, 1, 2))); /* (blocks program) */
void error_message(char *msg, ...) __attribute__ ((format (printf, 1, 2))); /* (blocks program) */
/* (doesn't block program)
* (this is not necessarily stackable, e.g. only one wait_message at a time) */
void wait_message(char *msg, ...) __attribute__ ((format (printf, 1, 2)));
/* call this to finish the wait on wait_message */
void remove_wait_message(void);
/* monitor progression of something (downloading a file, etc)
* if size of progression is unknown, use `0' */
void init_progression(char *msg, int size);
void update_progression(int current_size);
void end_progression(void);
enum frontend_return { RETURN_OK, RETURN_BACK, RETURN_ERROR };
/* Yes == RETURN_OK No == RETURN_ERROR Back == RETURN_BACK */
enum frontend_return ask_yes_no(char *msg);
/* [elems] NULL terminated array of char*
* [choice] address of a (unitialized) char* */
enum frontend_return ask_from_list(char *msg, char ** elems, char ** choice);
enum frontend_return ask_from_list_comments(char *msg, char ** elems, char ** elems_comments, char ** choice);
/* [questions] NULL terminated array of char*
* [answers] address of a (unitialized) char**, will contain a non-NULL terminated array of char*
* [callback_func] function called at most when the answers change; it can examine the array of char* and assign some new char* */
enum frontend_return ask_from_entries(char *msg, char ** questions, char *** answers, int entry_size, void (*callback_func)(char ** strings));
#endif

43
frontend-common.c Normal file
View File

@ -0,0 +1,43 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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 <stdlib.h>
#include <stdarg.h>
#include "frontend.h"
void info_message(char *msg, ...)
{
va_list args;
va_start(args, msg);
vinfo_message(msg, args);
va_end(args);
}
void wait_message(char *msg, ...)
{
va_list args;
va_start(args, msg);
vwait_message(msg, args);
va_end(args);
}
void error_message(char *msg, ...)
{
va_list args;
va_start(args, msg);
verror_message(msg, args);
va_end(args);
}

50
frontend.h Normal file
View File

@ -0,0 +1,50 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* For doc please read doc/documented..frontend.h
*/
#ifndef _FRONTEND_H_
#define _FRONTEND_H_
#include <stdarg.h>
enum return_type { RETURN_OK, RETURN_BACK, RETURN_ERROR };
void init_frontend(char * welcome_msg);
void finish_frontend(void);
void error_message(char *msg, ...) __attribute__ ((format (printf, 1, 2))); /* blocking */
void info_message(char *msg, ...) __attribute__ ((format (printf, 1, 2))); /* blocking */
void wait_message(char *msg, ...) __attribute__ ((format (printf, 1, 2))); /* non-blocking */
void remove_wait_message(void);
void init_progression(char *msg, int size);
void update_progression(int current_size);
void end_progression(void);
enum return_type ask_yes_no(char *msg);
enum return_type ask_from_list(char *msg, char ** elems, char ** choice);
enum return_type ask_from_list_comments(char *msg, char ** elems, char ** elems_comments, char ** choice);
enum return_type ask_from_entries(char *msg, char ** questions, char *** answers, int entry_size, void (*callback_func)(char ** strings));
void verror_message(char *msg, va_list ap);
void vinfo_message(char *msg, va_list ap);
void vwait_message(char *msg, va_list ap);
#endif

44
init-libc-headers.h Normal file
View File

@ -0,0 +1,44 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mount.h>
#include <linux/un.h>
#include <errno.h>
#include <signal.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <linux/unistd.h>
#include <sys/select.h>
#ifndef SOCK_STREAM
#define SOCK_STREAM 1
#endif
static inline _syscall3(int, syslog, int, type, char *, bufp, int, len);
static inline _syscall3(int, reboot, int, magic, int, magic2, int, flag);

497
init.c Normal file
View File

@ -0,0 +1,497 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#ifndef INIT_HEADERS
#include "init-libc-headers.h"
#else
#include INIT_HEADERS
#endif
#include "config-stage1.h"
#if defined(__powerpc__)
#define TIOCSCTTY 0x540
#endif
char * env[] = {
"PATH=/usr/bin:/bin:/sbin:/usr/sbin:/mnt/sbin:/mnt/usr/sbin:/mnt/bin:/mnt/usr/bin",
"LD_LIBRARY_PATH=/lib:/usr/lib:/mnt/lib:/mnt/usr/lib:/usr/X11R6/lib:/mnt/usr/X11R6/lib",
"HOME=/",
"TERM=linux",
"TERMINFO=/etc/terminfo",
NULL
};
/*
* this needs to handle the following cases:
*
* 1) run from a CD root filesystem
* 2) run from a read only nfs rooted filesystem
* 3) run from a floppy
* 4) run from a floppy that's been loaded into a ramdisk
*
*/
int testing;
int klog_pid;
void fatal_error(char *msg)
{
printf("FATAL ERROR IN INIT: %s\n\nI can't recover from this, please reboot manually and send bugreport.\n", msg);
while (1);
}
void print_error(char *msg)
{
printf("E: %s\n", msg);
}
void print_warning(char *msg)
{
printf("W: %s\n", msg);
}
void print_int_init(int fd, int i)
{
char buf[10];
char * chptr = buf + 9;
int j = 0;
if (i < 0)
{
write(1, "-", 1);
i = -1 * i;
}
while (i)
{
*chptr-- = '0' + (i % 10);
j++;
i = i / 10;
}
write(fd, chptr + 1, j);
}
void print_str_init(int fd, char * string)
{
write(fd, string, strlen(string));
}
/* fork to:
* (1) watch /proc/kmsg and copy the stuff to /dev/tty4
* (2) listens to /dev/log and copy also this stuff (log from programs)
*/
void doklog()
{
fd_set readset, unixs;
int in, out, i;
int log;
int s;
int sock = -1;
struct sockaddr_un sockaddr;
char buf[1024];
int readfd;
/* open kernel message logger */
in = open("/proc/kmsg", O_RDONLY,0);
if (in < 0) {
print_error("could not open /proc/kmsg");
return;
}
if ((log = open("/tmp/syslog", O_WRONLY | O_CREAT, 0644)) < 0) {
print_error("error opening /tmp/syslog");
sleep(5);
return;
}
if ((klog_pid = fork())) {
close(in);
close(log);
return;
} else {
close(0);
close(1);
close(2);
}
out = open("/dev/tty4", O_WRONLY, 0);
if (out < 0)
print_warning("couldn't open tty for syslog -- still using /tmp/syslog\n");
/* now open the syslog socket */
// ############# LINUX 2.4 /dev/log IS BUGGED! --> apparently the syslogs can't reach me, and it's full up after a while
// sockaddr.sun_family = AF_UNIX;
// strncpy(sockaddr.sun_path, "/dev/log", UNIX_PATH_MAX);
// sock = socket(AF_UNIX, SOCK_STREAM, 0);
// if (sock < 0) {
// printf("error creating socket: %d\n", errno);
// sleep(5);
// }
//
// print_str_init(log, "] got socket\n");
// if (bind(sock, (struct sockaddr *) &sockaddr, sizeof(sockaddr.sun_family) + strlen(sockaddr.sun_path))) {
// print_str_init(log, "] bind error: ");
// print_int_init(log, errno);
// print_str_init(log, "\n");
// sleep(// }
//
// print_str_init(log, "] bound socket\n");
// chmod("/dev/log", 0666);
// if (listen(sock, 5)) {
// print_str_init(log, "] listen error: ");
// print_int_init(log, errno);
// print_str_init(log, "\n");
// sleep(5);
// }
/* disable on-console syslog output */
syslog(8, NULL, 1);
print_str_init(log, "] kernel/system logger ok\n");
FD_ZERO(&unixs);
while (1) {
memcpy(&readset, &unixs, sizeof(unixs));
if (sock >= 0)
FD_SET(sock, &readset);
FD_SET(in, &readset);
i = select(20, &readset, NULL, NULL, NULL);
if (i <= 0)
continue;
/* has /proc/kmsg things to tell us? */
if (FD_ISSET(in, &readset)) {
i = read(in, buf, sizeof(buf));
if (i > 0) {
if (out >= 0)
write(out, buf, i);
write(log, buf, i);
}
}
/* examine some fd's in the hope to find some syslog outputs from programs */
for (readfd = 0; readfd < 20; ++readfd) {
if (FD_ISSET(readfd, &readset) && FD_ISSET(readfd, &unixs)) {
i = read(readfd, buf, sizeof(buf));
if (i > 0) {
/* grep out the output of RPM telling that it installed/removed some packages */
if (!strstr(buf, "mdk installed") && !strstr(buf, "mdk removed")) {
if (out >= 0)
write(out, buf, i);
write(log, buf, i);
}
} else if (i == 0) {
/* socket closed */
close(readfd);
FD_CLR(readfd, &unixs);
}
}
}
/* the socket has moved, new stuff to do */
if (sock >= 0 && FD_ISSET(sock, &readset)) {
s = sizeof(sockaddr);
readfd = accept(sock, (struct sockaddr *) &sockaddr, &s);
if (readfd < 0) {
char * msg_error = "] error in accept\n";
if (out >= 0)
write(out, msg_error, strlen(msg_error));
write(log, msg_error, strlen(msg_error));
close(sock);
sock = -1;
}
else
FD_SET(readfd, &unixs);
}
}
}
#define LOOP_CLR_FD 0x4C01
void del_loop(char *device)
{
int fd;
if ((fd = open(device, O_RDONLY, 0)) < 0) {
printf("del_loop open failed\n");
return;
}
if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
printf("del_loop ioctl failed");
return;
}
close(fd);
}
struct filesystem
{
char * dev;
char * name;
char * fs;
int mounted;
};
/* attempt to unmount all filesystems in /proc/mounts */
void unmount_filesystems(void)
{
int fd, size;
char buf[65535]; /* this should be big enough */
char *p;
struct filesystem fs[500];
int numfs = 0;
int i, nb;
printf("unmounting filesystems...\n");
fd = open("/proc/mounts", O_RDONLY, 0);
if (fd < 1) {
print_error("failed to open /proc/mounts");
sleep(2);
return;
}
size = read(fd, buf, sizeof(buf) - 1);
buf[size] = '\0';
close(fd);
p = buf;
while (*p) {
fs[numfs].mounted = 1;
fs[numfs].dev = p;
while (*p != ' ') p++;
*p++ = '\0';
fs[numfs].name = p;
while (*p != ' ') p++;
*p++ = '\0';
fs[numfs].fs = p;
while (*p != ' ') p++;
*p++ = '\0';
while (*p != '\n') p++;
p++;
if (strcmp(fs[numfs].name, "/") != 0) numfs++; /* skip if root, no need to take initrd root in account */
}
/* Pixel's ultra-optimized sorting algorithm:
multiple passes trying to umount everything until nothing moves
anymore (a.k.a holy shotgun method) */
do {
nb = 0;
for (i = 0; i < numfs; i++) {
/*printf("trying with %s\n", fs[i].name);*/
if (fs[i].mounted && umount(fs[i].name) == 0) {
if (strncmp(fs[i].dev + sizeof("/dev/") - 1, "loop",
sizeof("loop") - 1) == 0)
del_loop(fs[i].dev);
printf("\t%s\n", fs[i].name);
fs[i].mounted = 0;
nb++;
}
}
} while (nb);
for (i = nb = 0; i < numfs; i++)
if (fs[i].mounted) {
printf("\t%s umount failed\n", fs[i].name);
if (strcmp(fs[i].fs, "ext2") == 0) nb++; /* don't count not-ext2 umount failed */
}
if (nb) {
printf("failed to umount some filesystems\n");
while (1);
}
}
int exit_value_rescue = 66;
#define DEV_PERM 00400|00200|00040|00020
#define CHR_DEV 0020000|DEV_PERM
#define BLK_DEV 0060000|DEV_PERM
static _syscall3(int,mknod,char *,a1,mode_t,a2,dev_t,a3)
int main(int argc, char **argv)
{
pid_t installpid, childpid;
int wait_status;
int fd;
int abnormal_termination = 0;
int end_stage2 = 0;
//char *argv2[4] = {"ls","-l","/dev/",0};
/* getpid() != 1 should work, by linuxrc tends to get a larger pid */
testing = (getpid() > 50);
/*
mknod("/dev/ram3", BLK_DEV, MKDEV(1,3));
mknod("/dev/fd0", BLK_DEV, MKDEV(2,0));
mknod("/dev/loop3", BLK_DEV, MKDEV(7,3));
mknod("/dev/mem", CHR_DEV, MKDEV(1,1));
mknod("/dev/null", CHR_DEV, MKDEV(1,3));
mknod("/dev/ptyp0", CHR_DEV, MKDEV(2,0));
mknod("/dev/ttyp0", CHR_DEV, MKDEV(3,0));
mknod("/dev/tty0", CHR_DEV, MKDEV(4,0));
mknod("/dev/tty1", CHR_DEV, MKDEV(4,1));
mknod("/dev/tty2", CHR_DEV, MKDEV(4,2));
mknod("/dev/tty3", CHR_DEV, MKDEV(4,3));
mknod("/dev/tty4", CHR_DEV, MKDEV(4,4));
mknod("/dev/tty5", CHR_DEV, MKDEV(4,5));
mknod("/dev/tty6", CHR_DEV, MKDEV(4,6));
mknod("/dev/tty7", CHR_DEV, MKDEV(4,7));
mknod("/dev/ttyS0", CHR_DEV, MKDEV(4,64));
mknod("/dev/console", CHR_DEV, MKDEV(5,1));
mknod("/dev/fb0", CHR_DEV, MKDEV(29,0));
mknod("/dev/ppp", CHR_DEV, MKDEV(108,0));
*/
//execve("/bin/ls",argv2,0);
if (!testing) {
/* turn off screen blanking */
printf("\033[9;0]");
printf("\033[8]");
}
else
printf("*** TESTING MODE ***\n");
printf("\n\t\t\t\033[1;40mWelcome to \033[1;36mALT Linux\033[0;39m\n\n");
if (!testing) {
if (mount("/proc", "/proc", "proc", 0, NULL))
fatal_error("Unable to mount proc filesystem");
}
/* ignore Control-C and keyboard stop signals */
signal(SIGINT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
if (!testing) {
fd = open("/dev/tty1", O_RDWR, 0);
if (fd < 0)
/* try with devfs */
fd = open("/dev/vc/1", O_RDWR, 0);
if (fd < 0)
fatal_error("failed to open /dev/tty1 and /dev/vc/1");
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
close(fd);
}
/* I set me up as session leader (probably not necessary?) */
setsid();
if (ioctl(0, TIOCSCTTY, NULL))
print_error("could not set new controlling tty");
if (!testing) {
char my_hostname[] = "localhost.localdomain";
sethostname(my_hostname, sizeof(my_hostname));
/* the default domainname (as of 2.0.35) is "(none)", which confuses
glibc */
setdomainname("", 0);
}
if (!testing)
doklog();
/* Go into normal init mode - keep going, and then do a orderly shutdown
when:
1) install exits
2) we receive a SIGHUP
*/
printf("If more people were to meet doing raklets, this planet\n");
printf("would be a safer place.\n");
printf("\n");
printf("Running install...\n");
if (!(installpid = fork())) {
/* child */
char * child_argv[2];
child_argv[0] = "/sbin/stage1";
child_argv[1] = NULL;
execve(child_argv[0], child_argv, env);
printf("error in exec of stage1 :-(\n");
return 0;
}
while (!end_stage2) {
childpid = wait4(-1, &wait_status, 0, NULL);
if (childpid == installpid)
end_stage2 = 1;
}
if (!WIFEXITED(wait_status) || (WEXITSTATUS(wait_status) != 0 && WEXITSTATUS(wait_status) != exit_value_rescue)) {
printf("wait_status: %i, install exited abnormally :-( ", wait_status);
if (WIFSIGNALED(wait_status))
printf("-- received signal %d", WTERMSIG(wait_status));
printf("\n");
abnormal_termination = 1;
} else if (WIFEXITED(wait_status) && WEXITSTATUS(wait_status) == exit_value_rescue) {
kill(klog_pid, 9);
printf("exiting init -- giving hand to rescue\n");
return 0;
} else
printf("install succeeded\n");
if (testing)
return 0;
sync(); sync();
printf("sending termination signals...");
kill(-1, 15);
sleep(2);
printf("done\n");
printf("sending kill signals...");
kill(-1, 9);
sleep(2);
printf("done\n");
unmount_filesystems();
if (!abnormal_termination) {
printf("rebooting system\n");
sleep(2);
reboot(0xfee1dead, 672274793, 0x01234567);
} else {
printf("you may safely reboot your system\n");
while (1);
}
return 0;
}

20
insmod.h Normal file
View File

@ -0,0 +1,20 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
#ifndef _INSMOD_INTERFACE_H_
#define _INSMOD_INTERFACE_H_
int insmod_call(char * full_filename, char * params);
#endif

143
log Normal file
View File

@ -0,0 +1,143 @@
rm -rf ./tmp_rpm
mkdir ./tmp_rpm
pushd ./tmp_rpm; \
for f in `cat ./../req`; do \
rpm2cpio /user/ALT/Sisyphus/files/i586/RPMS/$f-*.rpm | cpio -id; \
done
/mouse/installer/mdk-stage1/tmp_rpm /mouse/installer/mdk-stage1
80 blocks
132 blocks
2518 blocks
make[1]: Entering directory `/mouse/installer/mdk-stage1/mar'
make[1]: ãÅÌØ `all' ÎÅ ÔÒÅÂÕÅÔ ×ÙÐÏÌÎÅÎÉÑ ËÏÍÁÎÄ.
make[1]: Leaving directory `/mouse/installer/mdk-stage1/mar'
make[1]: Entering directory `/mouse/installer/mdk-stage1/pci-resource'
perl update-pci-ids.pl > pci-ids.h || rm -f pci-ids.h
Can't locate /usr/bin/merge2pcitable.pl in @INC (@INC contains: /etc/perl5 /usr/lib/perl5/i386-linux /usr/lib/perl5 /usr/local/lib/perl5/site_perl/5.8.1/i386-linux /usr/local/lib/perl5/site_perl/5.8.1 /usr/local/lib/perl5/site_perl /usr/lib/perl5/vendor_perl/i386-linux /usr/lib/perl5/vendor_perl /usr/lib/perl5/vendor_perl .) at update-pci-ids.pl line 7.
make[1]: Leaving directory `/mouse/installer/mdk-stage1/pci-resource'
make[1]: Entering directory `/mouse/installer/mdk-stage1/usb-resource'
perl update-usb-ids.pl > usb-ids.h || rm -f usb-ids.h
Can't locate /usr/bin/merge2pcitable.pl in @INC (@INC contains: /etc/perl5 /usr/lib/perl5/i386-linux /usr/lib/perl5 /usr/local/lib/perl5/site_perl/5.8.1/i386-linux /usr/local/lib/perl5/site_perl/5.8.1 /usr/local/lib/perl5/site_perl /usr/lib/perl5/vendor_perl/i386-linux /usr/lib/perl5/vendor_perl /usr/lib/perl5/vendor_perl .) at update-usb-ids.pl line 33.
make[1]: Leaving directory `/mouse/installer/mdk-stage1/usb-resource'
make[1]: Entering directory `/mouse/installer/mdk-stage1/insmod-busybox'
make[1]: ãÅÌØ `all' ÎÅ ÔÒÅÂÕÅÔ ×ÙÐÏÌÎÅÎÉÑ ËÏÍÁÎÄ.
make[1]: Leaving directory `/mouse/installer/mdk-stage1/insmod-busybox'
make[1]: Entering directory `/mouse/installer/mdk-stage1/slang'
make[1]: ãÅÌØ `all' ÎÅ ÔÒÅÂÕÅÔ ×ÙÐÏÌÎÅÎÉÑ ËÏÍÁÎÄ.
make[1]: Leaving directory `/mouse/installer/mdk-stage1/slang'
make[1]: Entering directory `/mouse/installer/mdk-stage1/newt'
make[1]: ãÅÌØ `all' ÎÅ ÔÒÅÂÕÅÔ ×ÙÐÏÌÎÅÎÉÑ ËÏÍÁÎÄ.
make[1]: Leaving directory `/mouse/installer/mdk-stage1/newt'
make[1]: Entering directory `/mouse/installer/mdk-stage1/ppp/pppd'
gcc -D_linux_=1 -DHAVE_PATHS_H -DIPX_CHANGE -DHAVE_MULTILINK -DHAVE_MMAP -I../include -DCHAPMS=1 -DUSE_CRYPT=1 -DHAVE_CRYPT_H=1 -DMPPE=1 -DHAS_SHADOW -DUSE_PAM -DPLUGIN -c -o auth.o auth.c
auth.c:58:31: security/pam_appl.h: No such file or directory
auth.c:1056: syntax error before '*' token
auth.c:1056: warning: data definition has no type or storage class
auth.c:1064: warning: `struct pam_response' declared inside parameter list
auth.c:1064: warning: its scope is only this definition or declaration, which is probably not what you want
auth.c:1064: warning: `struct pam_message' declared inside parameter list
auth.c: In function `PAM_conv':
auth.c:1071: sizeof applied to an incomplete type
auth.c:1072: `PAM_CONV_ERR' undeclared (first use in this function)
auth.c:1072: (Each undeclared identifier is reported only once
auth.c:1072: for each function it appears in.)
auth.c:1075: dereferencing pointer to incomplete type
auth.c:1076: `PAM_PROMPT_ECHO_ON' undeclared (first use in this function)
auth.c:1077: invalid use of undefined type `struct pam_response'
auth.c:1077: dereferencing pointer to incomplete type
auth.c:1077: `PAM_SUCCESS' undeclared (first use in this function)
auth.c:1078: invalid use of undefined type `struct pam_response'
auth.c:1078: dereferencing pointer to incomplete type
auth.c:1081: `PAM_PROMPT_ECHO_OFF' undeclared (first use in this function)
auth.c:1082: invalid use of undefined type `struct pam_response'
auth.c:1082: dereferencing pointer to incomplete type
auth.c:1083: invalid use of undefined type `struct pam_response'
auth.c:1083: dereferencing pointer to incomplete type
auth.c:1086: `PAM_TEXT_INFO' undeclared (first use in this function)
auth.c:1088: `PAM_ERROR_MSG' undeclared (first use in this function)
auth.c:1090: invalid use of undefined type `struct pam_response'
auth.c:1090: dereferencing pointer to incomplete type
auth.c:1091: invalid use of undefined type `struct pam_response'
auth.c:1091: dereferencing pointer to incomplete type
auth.c: At top level:
auth.c:1104: variable `PAM_conversation' has initializer but incomplete type
auth.c:1105: warning: excess elements in struct initializer
auth.c:1105: warning: (near initialization for `PAM_conversation')
auth.c:1107: warning: excess elements in struct initializer
auth.c:1107: warning: (near initialization for `PAM_conversation')
auth.c: In function `plogin':
auth.c:1132: `PAM_SUCCESS' undeclared (first use in this function)
auth.c:1144: `PAM_TTY' undeclared (first use in this function)
auth.c:1149: `PAM_SILENT' undeclared (first use in this function)
auth.c: In function `plogout':
auth.c:1250: `PAM_SILENT' undeclared (first use in this function)
auth.c: At top level:
auth.c:1104: storage size of `PAM_conversation' isn't known
make[1]: *** [auth.o] ïÛÉÂËÁ 1
make[1]: Leaving directory `/mouse/installer/mdk-stage1/ppp/pppd'
make[1]: Entering directory `/mouse/installer/mdk-stage1/rp-pppoe/src'
gcc -Wall -Os -fomit-frame-pointer '-DPPPOE_PATH="/sbin/pppoe"' '-DPPPD_PATH="/sbin/pppd"' '-DVERSION="3.0-stg1"' -I. -I../../tmp_rpm/usr/lib/dietlibc/include -I../../tmp_rpm/usr/include -c if.c -o if.o
In file included from if.c:32:
/usr/include/net/ethernet.h:35: syntax error before "u_int8_t"
/usr/include/net/ethernet.h:41: syntax error before "u_int8_t"
/usr/include/net/ethernet.h:43: syntax error before "ether_type"
if.c: In function `openInterface':
if.c:456: warning: implicit declaration of function `strncpy'
make[1]: *** [if.o] ïÛÉÂËÁ 1
make[1]: Leaving directory `/mouse/installer/mdk-stage1/rp-pppoe/src'
make[1]: Entering directory `/mouse/installer/mdk-stage1/pcmcia'
gcc -Wall -Os -fomit-frame-pointer -pipe -c -I.. -D_BSD_SOURCE -I. -I../tmp_rpm/usr/lib/dietlibc/include -I../tmp_rpm/usr/include -c pcmcia_probe.c -o pcmcia_probe.o
gcc -Wall -Os -fomit-frame-pointer -pipe -c -I.. -D_BSD_SOURCE -I. -I../tmp_rpm/usr/lib/dietlibc/include -I../tmp_rpm/usr/include -c cardmgr.c -o cardmgr.o
cardmgr.c: In function `lookup_card':
cardmgr.c:478: warning: implicit declaration of function `strncmp'
cardmgr.c: In function `adjust_resources':
cardmgr.c:1224: warning: long unsigned int format, u_long arg (arg 3)
cardmgr.c:1224: warning: long unsigned int format, u_long arg (arg 4)
cardmgr.c:1224: warning: long unsigned int format, u_long arg (arg 3)
cardmgr.c:1224: warning: long unsigned int format, u_long arg (arg 4)
gcc -Wall -Os -fomit-frame-pointer -pipe -c -I.. -D_BSD_SOURCE -I. -I../tmp_rpm/usr/lib/dietlibc/include -I../tmp_rpm/usr/include -c lex_config.c -o lex_config.o
lex_config.l: In function `lex_string':
lex_config.l:146: warning: implicit declaration of function `strncpy'
lex_config.l: In function `parse_configfile':
lex_config.l:265: warning: implicit declaration of function `yyparse'
lex_config.l: At top level:
lex_config.l:468: warning: `yyunput' defined but not used
gcc -Wall -Os -fomit-frame-pointer -pipe -c -I.. -D_BSD_SOURCE -I. -I../tmp_rpm/usr/lib/dietlibc/include -I../tmp_rpm/usr/include -c yacc_config.c -o yacc_config.o
y.tab.c: In function `yyparse':
y.tab.c:556: warning: implicit declaration of function `yylex'
ar -cru libpcmcia.a pcmcia_probe.o cardmgr.o lex_config.o yacc_config.o
ranlib libpcmcia.a
gcc -Wall -Os -fomit-frame-pointer -pipe -c -I.. -D_BSD_SOURCE -I../tmp_rpm/usr/lib/dietlibc/include -I. -I../tmp_rpm/usr/include -c pcmcia_probe.c -o pcmcia_probe-DIET.o
gcc -Wall -Os -fomit-frame-pointer -pipe -c -I.. -D_BSD_SOURCE -I../tmp_rpm/usr/lib/dietlibc/include -I. -I../tmp_rpm/usr/include -c cardmgr.c -o cardmgr-DIET.o
cardmgr.c: In function `lookup_card':
cardmgr.c:478: warning: implicit declaration of function `strncmp'
cardmgr.c: In function `adjust_resources':
cardmgr.c:1224: warning: long unsigned int format, u_long arg (arg 3)
cardmgr.c:1224: warning: long unsigned int format, u_long arg (arg 4)
cardmgr.c:1224: warning: long unsigned int format, u_long arg (arg 3)
cardmgr.c:1224: warning: long unsigned int format, u_long arg (arg 4)
gcc -Wall -Os -fomit-frame-pointer -pipe -c -I.. -D_BSD_SOURCE -I../tmp_rpm/usr/lib/dietlibc/include -I. -I../tmp_rpm/usr/include -c lex_config.c -o lex_config-DIET.o
lex_config.l: In function `lex_string':
lex_config.l:146: warning: implicit declaration of function `strncpy'
lex_config.l: In function `parse_configfile':
lex_config.l:265: warning: implicit declaration of function `yyparse'
lex_config.l: At top level:
lex_config.l:468: warning: `yyunput' defined but not used
gcc -Wall -Os -fomit-frame-pointer -pipe -c -I.. -D_BSD_SOURCE -I../tmp_rpm/usr/lib/dietlibc/include -I. -I../tmp_rpm/usr/include -c yacc_config.c -o yacc_config-DIET.o
y.tab.c: In function `yyparse':
y.tab.c:556: warning: implicit declaration of function `yylex'
ar -cru libpcmcia-DIET.a pcmcia_probe-DIET.o cardmgr-DIET.o lex_config-DIET.o yacc_config-DIET.o
ranlib libpcmcia-DIET.a
make[1]: Leaving directory `/mouse/installer/mdk-stage1/pcmcia'
cc -DVERSION=\""strawberry"\" -DSPAWN_SHELL -DDISTRIB_NAME=\""ALT Linux"\" -Os -pipe -Wall -fomit-frame-pointer -DINIT_HEADERS=\"minilibc.h\" -c minilibc.c
In file included from /usr/include/linux/config.h:4,
from /usr/include/linux/net.h:21,
from minilibc.h:53,
from minilibc.c:25:
/usr/include/linux/autoconf.h:1:2: #error Invalid kernel header included in userspace
In file included from minilibc.c:25:
minilibc.h:135: warning: conflicting types for built-in function `strncmp'
minilibc.h:137: warning: conflicting types for built-in function `strstr'
minilibc.h:138: warning: conflicting types for built-in function `strncpy'
minilibc.h:143: warning: conflicting types for built-in function `printf'
make: *** [minilibc.o] ïÛÉÂËÁ 1

85
log.c Normal file
View File

@ -0,0 +1,85 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include "stage1.h"
#include "log.h"
static FILE * logfile = NULL;
void vlog_message(const char * s, va_list args)
{
fprintf(logfile, "* ");
vfprintf(logfile, s, args);
fprintf(logfile, "\n");
fflush(logfile);
}
void log_message(const char * s, ...)
{
va_list args;
if (!logfile) {
fprintf(stderr, "Log is not open!\n");
return;
}
va_start(args, s);
vlog_message(s, args);
va_end(args);
return;
}
void log_perror(char *msg)
{
log_message("%s: %s", msg, strerror(errno));
}
void open_log(void)
{
if (!IS_TESTING) {
logfile = fopen("/dev/tty3", "w");
if (!logfile)
logfile = fopen("/tmp/install.log", "a");
}
else
logfile = fopen("debug.log", "w");
}
void close_log(void)
{
if (logfile) {
log_message("stage1: disconnecting life support systems");
fclose(logfile);
}
}

34
log.h Normal file
View File

@ -0,0 +1,34 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#ifndef _LOG_H_
#define _LOG_H_
#include <stdarg.h>
void log_message(const char * s, ...) __attribute__ ((format (printf, 1, 2)));
void vlog_message(const char * s, va_list args);
void log_perror(char *msg);
void open_log(void);
void close_log(void);
#endif

171
lomount.c Normal file
View File

@ -0,0 +1,171 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/* This code comes from util-linux-2.10n (mount/lomount.c)
* (this is a simplified version of this code)
*/
#include <sys/types.h>
#include <sys/mount.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "stage1.h"
#include "frontend.h"
#include "log.h"
#include "mount.h"
#include "modules.h"
#include "lomount.h"
#define LO_NAME_SIZE 64
#define LO_KEY_SIZE 32
struct loop_info
{
int lo_number; /* ioctl r/o */
dev_t lo_device; /* ioctl r/o */
unsigned long lo_inode; /* ioctl r/o */
dev_t lo_rdevice; /* ioctl r/o */
int lo_offset;
int lo_encrypt_type;
int lo_encrypt_key_size; /* ioctl w/o */
int lo_flags; /* ioctl r/o */
char lo_name[LO_NAME_SIZE];
unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
unsigned long lo_init[2];
char reserved[4];
};
#define LOOP_SET_FD 0x4C00
#define LOOP_CLR_FD 0x4C01
#define LOOP_SET_STATUS 0x4C02
#define LOOP_GET_STATUS 0x4C03
int
set_loop (const char *device, const char *file)
{
struct loop_info loopinfo;
int fd, ffd, mode;
mode = O_RDONLY;
if ((ffd = open (file, mode)) < 0)
return 1;
if ((fd = open (device, mode)) < 0) {
close(ffd);
return 1;
}
memset(&loopinfo, 0, sizeof (loopinfo));
strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
loopinfo.lo_name[LO_NAME_SIZE - 1] = 0;
loopinfo.lo_offset = 0;
#ifdef MCL_FUTURE
/*
* Oh-oh, sensitive data coming up. Better lock into memory to prevent
* passwd etc being swapped out and left somewhere on disk.
*/
if(mlockall(MCL_CURRENT|MCL_FUTURE)) {
log_message("CRITICAL Couldn't lock into memory! %s (memlock)", strerror(errno));
return 1;
}
#endif
if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
close(fd);
close(ffd);
return 1;
}
if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
(void) ioctl (fd, LOOP_CLR_FD, 0);
close(fd);
close(ffd);
return 1;
}
close(fd);
close(ffd);
return 0;
}
char * loopdev = "/dev/loop3"; /* Ugly. But do I care? */
void
del_loop(void)
{
int fd;
if ((fd = open (loopdev, O_RDONLY)) < 0)
return;
if (ioctl (fd, LOOP_CLR_FD, 0) < 0)
return;
close (fd);
}
static char * where_mounted = NULL;
int
lomount(char *loopfile, char *where)
{
long int flag;
flag = MS_MGC_VAL;
flag |= MS_RDONLY;
my_insmod("loop", ANY_DRIVER_TYPE, NULL);
if (set_loop(loopdev, loopfile)) {
log_message("set_loop failed on %s (%s)", loopdev, strerror(errno));
return 1;
}
if (my_mount(loopdev, where, "iso9660", 0)) {
del_loop();
return 1;
}
where_mounted = strdup(where);
log_message("lomount succeeded for %s on %s", loopfile, where);
return 0;
}
int
loumount()
{
if (where_mounted) {
umount(where_mounted);
where_mounted = NULL;
}
del_loop();
return 0;
}

21
lomount.h Normal file
View File

@ -0,0 +1,21 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
#ifndef LOMOUNT_H
#define LOMOUNT_H
int lomount(char *loopfile, char *where);
int loumount(void);
#endif

251
minilibc.c Normal file
View File

@ -0,0 +1,251 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#define MINILIBC_INTERNAL
#include "minilibc.h"
int atexit (void (*__func) (void))
{
return 0;
}
void exit()
{
_do_exit(0);
for (;;); /* Shut up gcc */
}
char ** _environ = NULL;
int errno = 0;
void _init (int __status)
{
}
void __libc_init_first (int __status)
{
}
int __libc_start_main (int (*main) (int, char **, char **), int argc,
char **argv, void (*init) (void), void (*fini) (void),
void (*rtld_fini) (void), void *stack_end)
{
exit ((*main) (argc, argv, NULL));
/* never get here */
return 0;
}
void _fini (int __status)
{
}
inline int socket(int a, int b, int c)
{
unsigned long args[] = { a, b, c };
return socketcall(SYS_SOCKET, args);
}
inline int bind(int a, void * b, int c)
{
unsigned long args[] = { a, (long) b, c };
return socketcall(SYS_BIND, args);
}
inline int listen(int a, int b)
{
unsigned long args[] = { a, b, 0 };
return socketcall(SYS_LISTEN, args);
}
inline int accept(int a, void * addr, void * addr2)
{
unsigned long args[] = { a, (long) addr, (long) addr2 };
return socketcall(SYS_ACCEPT, args);
}
void sleep(int secs)
{
struct timeval tv;
tv.tv_sec = secs;
tv.tv_usec = 0;
select(0, NULL, NULL, NULL, &tv);
}
int strlen(const char * string)
{
int i = 0;
while (*string++) i++;
return i;
}
char * strncpy(char * dst, const char * src, int len)
{
char * chptr = dst;
int i = 0;
while (*src && i < len) *dst++ = *src++, i++;
if (i < len) *dst = '\0';
return chptr;
}
char * strcpy(char * dst, const char * src)
{
char * chptr = dst;
while (*src) *dst++ = *src++;
*dst = '\0';
return chptr;
}
void * memcpy(void * dst, const void * src, size_t count)
{
char * a = dst;
const char * b = src;
while (count--)
*a++ = *b++;
return dst;
}
int strcmp(const char * a, const char * b)
{
int i, j;
i = strlen(a); j = strlen(b);
if (i < j)
return -1;
else if (j < i)
return 1;
while (*a && (*a == *b)) a++, b++;
if (!*a) return 0;
if (*a < *b)
return -1;
else
return 1;
}
int strncmp(const char * a, const char * b, int len)
{
char buf1[1000], buf2[1000];
strncpy(buf1, a, len);
strncpy(buf2, b, len);
buf1[len] = '\0';
buf2[len] = '\0';
return strcmp(buf1, buf2);
}
char * strchr(char * str, int ch)
{
char * chptr;
chptr = str;
while (*chptr)
{
if (*chptr == ch) return chptr;
chptr++;
}
return NULL;
}
char * strstr(char *haystack, char *needle)
{
char * tmp = haystack;
while ((tmp = strchr(tmp, needle[0])) != NULL) {
int i = 1;
while (i < strlen(tmp) && i < strlen(needle) && tmp[i] == needle[i])
i++;
if (needle[i] == '\0')
return tmp;
tmp++;
}
return NULL;
}
/* Minimum printf which handles only characters, %d's and %s's */
void printf(char * fmt, ...)
{
char buf[2048];
char * start = buf;
char * chptr = buf;
va_list args;
char * strarg;
int numarg;
strncpy(buf, fmt, sizeof(buf));
va_start(args, fmt);
while (start)
{
while (*chptr != '%' && *chptr) chptr++;
if (*chptr == '%')
{
*chptr++ = '\0';
print_str_init(1, start);
switch (*chptr++)
{
case 's':
strarg = va_arg(args, char *);
print_str_init(1, strarg);
break;
case 'd':
numarg = va_arg(args, int);
print_int_init(1, numarg);
break;
}
start = chptr;
}
else
{
print_str_init(1, start);
start = NULL;
}
}
}

144
minilibc.h Normal file
View File

@ -0,0 +1,144 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#include <stdarg.h>
#define _LOOSE_KERNEL_NAMES 1
#define NULL ((void *) 0)
#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
#define WIFSIGNALED(status) (!WIFSTOPPED(status) && !WIFEXITED(status))
#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
#define WTERMSIG(status) ((status) & 0x7f)
#define WSTOPSIG(status) WEXITSTATUS(status)
#define WIFEXITED(status) (WTERMSIG(status) == 0)
#define MS_MGC_VAL 0xc0ed0000
#define isspace(a) (a == ' ' || a == '\t')
extern char ** _environ;
extern int errno;
/* Aieee, gcc 2.95+ creates a stub for posix_types.h on i386 which brings
glibc headers in and thus makes __FD_SET etc. not defined with 2.3+ kernels. */
#define _FEATURES_H 1
#include <linux/socket.h>
#include <linux/types.h>
#include <linux/time.h>
#include <linux/if.h>
#include <linux/un.h>
#include <linux/loop.h>
#include <linux/net.h>
#include <asm/posix_types.h>
#include <asm/termios.h>
#include <asm/ioctls.h>
#include <asm/unistd.h>
#include <asm/fcntl.h>
#include <asm/signal.h>
#ifndef MINILIBC_INTERNAL
static inline _syscall5(int,mount,const char *,spec,const char *,dir,const char *,type,unsigned long,rwflag,const void *,data);
static inline _syscall5(int,_newselect,int,n,fd_set *,rd,fd_set *,wr,fd_set *,ex,struct timeval *,timeval);
static inline _syscall4(int,wait4,pid_t,pid,int *,status,int,opts,void *,rusage)
static inline _syscall3(int,write,int,fd,const char *,buf,unsigned long,count)
static inline _syscall3(int,reboot,int,magic,int,magic_too,int,flag)
static inline _syscall3(int,execve,const char *,fn,void *,argv,void *,envp)
static inline _syscall3(int,read,int,fd,const char *,buf,unsigned long,count)
static inline _syscall3(int,open,const char *,fn,int,flags,mode_t,mode)
static inline _syscall3(int,ioctl,int,fd,int,request,void *,argp)
static inline _syscall2(int,dup2,int,one,int,two)
static inline _syscall2(int,kill,pid_t,pid,int,sig)
static inline _syscall2(int,symlink,const char *,a,const char *,b)
static inline _syscall2(int,chmod,const char * ,path,mode_t,mode)
static inline _syscall2(int,sethostname,const char *,name,int,len)
static inline _syscall2(int,setdomainname,const char *,name,int,len)
static inline _syscall2(int,setpgid,int,name,int,len)
static inline _syscall2(int,signal,int,num,void *,len)
static inline _syscall1(int,umount,const char *,dir)
static inline _syscall1(int,unlink,const char *,fn)
static inline _syscall1(int,close,int,fd)
static inline _syscall1(int,swapoff,const char *,fn)
static inline _syscall0(int,getpid)
static inline _syscall0(int,sync)
#ifdef __sparc__
/* Nonstandard fork calling convention :( */
static inline int fork(void) {
int __res;
__asm__ __volatile__ (
"mov %0, %%g1\n\t"
"t 0x10\n\t"
"bcc 1f\n\t"
"dec %%o1\n\t"
"sethi %%hi(%2), %%g1\n\t"
"st %%o0, [%%g1 + %%lo(%2)]\n\t"
"b 2f\n\t"
"mov -1, %0\n\t"
"1:\n\t"
"and %%o0, %%o1, %0\n\t"
"2:\n\t"
: "=r" (__res)
: "0" (__NR_fork), "i" (&errno)
: "g1", "o0", "cc");
return __res;
}
#else
static inline _syscall0(int,fork)
#endif
static inline _syscall0(pid_t,setsid)
static inline _syscall3(int,syslog,int, type, char *, buf, int, len);
#else
static inline _syscall5(int,_newselect,int,n,fd_set *,rd,fd_set *,wr,fd_set *,ex,struct timeval *,timeval);
static inline _syscall3(int,write,int,fd,const char *,buf,unsigned long,count)
static inline _syscall2(int,socketcall,int,code,unsigned long *, args)
#define __NR__do_exit __NR_exit
extern inline _syscall1(int,_do_exit,int,exitcode)
#endif
#define select _newselect
extern int errno;
inline int socket(int a, int b, int c);
inline int bind(int a, void * b, int c);
inline int listen(int a, int b);
inline int accept(int a, void * addr, void * addr2);
void sleep(int secs);
int strlen(const char * string);
char * strcpy(char * dst, const char * src);
void * memcpy(void * dst, const void * src, size_t count);
int strcmp(const char * a, const char * b);
int strncmp(const char * a, const char * b, int len);
char * strchr(char * str, int ch);
char * strstr(char *haystack, char *needle);
char * strncpy(char * dst, const char * src, int len);
void print_str_init(int fd, char * string);
void print_int_init(int fd, int i);
/* Minimum printf which handles only characters, %d's and %s's */
void printf(char * fmt, ...) __attribute__ ((format (printf, 1, 2)));

46
mkinitrd_helper/Makefile Normal file
View File

@ -0,0 +1,46 @@
#******************************************************************************
#
# Guillaume Cottenceau (gc@mandrakesoft.com)
#
# Copyright 2000 MandrakeSoft
#
# This software may be freely redistributed under the terms of the GNU
# 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.
#
#*****************************************************************************
top_dir = ..
include $(top_dir)/Makefile.common
VERSION = 1.1.1
DEFS = -DVERSION=\"$(VERSION)\"
MKINITRD_HELPER_SRC = mkinitrd_helper.c
MKINITRD_HELPER_LIBS = ../insmod-busybox/libinsmod-DIET.a
MKINITRD_HELPER_OBJS = $(subst .c,.o,$(MKINITRD_HELPER_SRC))
BIN = mkinitrd_helper
all: $(BIN)
clean:
rm -f *.o $(BIN)
FLAGS = -Wall -Os -fomit-frame-pointer -c
$(MKINITRD_HELPER_OBJS): %.o: %.c
$(CC) $(DEFS) $(DIETLIBC_INCLUDES) -I.. -c $< -o $@
mkinitrd_helper: $(MKINITRD_HELPER_OBJS) $(MKINITRD_HELPER_LIBS) $(DIETLIBC_LIBC)
$(CC) $(DIETLIBC_LDFLAGS_STAGE1) -o $@ $^
$(STRIPCMD) $@

View File

@ -0,0 +1,308 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2001 MandrakeSoft
*
* This software is covered by the GPL license.
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*
* This little program replaces usual sash and insmod.static based script
* from mkinitrd (that insmod modules, plus possibly mount a partition and
* losetup a loopback-based / on the partition).
*
*
* On my machine:
* gzipped sash + insmod.static 502491 bytes
* gzipped <this-program> 14243 bytes
*
* There will be room for linux-2.4 and many modules, now. Cool.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <signal.h>
#include "insmod.h"
int quiet = 0;
void vlog_message(const char * s, va_list args)
{
vprintf(s, args);
printf("\n");
}
void log_perror(char *msg)
{
perror(msg);
}
static void fatal_error(char *msg)
{
printf("[] E: %s\n[] giving hand to kernel.\n", msg);
exit(-1);
}
static void warning(char *msg)
{
printf("[] W: %s\n", msg);
}
static void parse_parms(const char * parm, char ** parm1, char ** parm2, char ** parm3)
{
char * ptr;
ptr = strchr(parm, '\n');
if (!ptr)
fatal_error("bad config file: no newline after parms");
*parm1 = malloc(ptr-parm+1); /* yup, never freed :-) */
memcpy(*parm1, parm, ptr-parm);
(*parm1)[ptr-parm] = '\0';
if (!parm2)
return;
*parm2 = strchr(*parm1, ' ');
if (!*parm2)
return;
**parm2 = '\0';
(*parm2)++;
if (!parm3)
return;
*parm3 = strchr(*parm2, ' ');
if (!*parm3)
return;
**parm3 = '\0';
(*parm3)++;
}
static void insmod_(const char * parm)
{
char * mod_name, * options;
parse_parms(parm, &mod_name, &options, NULL);
#ifdef DEBUG
printf("insmod %s options %s\n", mod_name, options);
#endif
if (!quiet)
printf("[] Loading module %s\n", mod_name);
if (insmod_call(mod_name, options))
perror("insmod failed");
}
static void mount_(const char * parm)
{
char * dev, * location, * fs;
unsigned long flags;
char * opts = NULL;
parse_parms(parm, &dev, &location, &fs);
#ifdef DEBUG
printf("mounting %s on %s as type %s\n", dev, location, fs);
#endif
if (!quiet)
printf("[] Mounting device containing loopback root filesystem\n");
flags = MS_MGC_VAL;
if (!strcmp(fs, "vfat"))
opts = "check=relaxed";
if (mount(dev, location, fs, flags, opts))
perror("mount failed");
}
#define LO_NAME_SIZE 64
#define LO_KEY_SIZE 32
struct loop_info
{
int lo_number; /* ioctl r/o */
dev_t lo_device; /* ioctl r/o */
unsigned long lo_inode; /* ioctl r/o */
dev_t lo_rdevice; /* ioctl r/o */
int lo_offset;
int lo_encrypt_type;
int lo_encrypt_key_size; /* ioctl w/o */
int lo_flags; /* ioctl r/o */
char lo_name[LO_NAME_SIZE];
unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
unsigned long lo_init[2];
char reserved[4];
};
#define LOOP_SET_FD 0x4C00
#define LOOP_CLR_FD 0x4C01
#define LOOP_SET_STATUS 0x4C02
static void set_loop_(const char * parm)
{
struct loop_info loopinfo;
int fd, ffd;
char * device, * file;
parse_parms(parm, &device, &file, NULL);
#ifdef DEBUG
printf("set_looping %s with %s\n", device, file);
#endif
if (!quiet)
printf("[] Setting up loopback file %s\n", file);
if ((ffd = open(file, O_RDWR)) < 0) {
perror("set_loop, opening file in rw");
exit(-1);
}
if ((fd = open(device, O_RDWR)) < 0) {
perror("set_loop, opening loop device in rw");
close(ffd);
exit(-1);
}
memset(&loopinfo, 0, sizeof (loopinfo));
strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
loopinfo.lo_name[LO_NAME_SIZE - 1] = 0;
loopinfo.lo_offset = 0;
if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
close(fd);
close(ffd);
perror("LOOP_SET_FD");
exit(-1);
}
if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
(void) ioctl (fd, LOOP_CLR_FD, 0);
close(fd);
close(ffd);
perror("LOOP_SET_STATUS");
exit(-1);
}
close(fd);
close(ffd);
}
#define MD_MAJOR 9
#define RAID_AUTORUN _IO (MD_MAJOR, 0x14)
#include <linux/raid/md_u.h>
static void raidautorun_(const char * parm)
{
char * device;
int fd;
parse_parms(parm, &device, NULL, NULL);
if (!quiet)
printf("[] Calling raid autorun for %s\n", device);
fd = open(device, O_RDWR, 0);
if (fd < 0) {
printf("raidautorun: failed to open %s: %d\n", device, errno);
return;
}
if (ioctl(fd, RAID_AUTORUN, 0)) {
printf("raidautorun: RAID_AUTORUN failed: %d\n", errno);
}
close(fd);
}
static int handle_command(char ** ptr, char * cmd_name, void (*cmd_func)(const char * parm))
{
if (!strncmp(*ptr, cmd_name, strlen(cmd_name))) {
*ptr = strchr(*ptr, '\n');
if (!*ptr)
fatal_error("Bad config file: no newline after command");
(*ptr)++;
cmd_func(*ptr);
*ptr = strchr(*ptr, '\n');
if (!*ptr)
exit(0);
(*ptr)++;
return 1;
}
return 0;
}
int main(int argc, char **argv)
{
int fd_conf, i;
char buf[5000];
char * ptr;
if (strstr(argv[0], "modprobe"))
exit(0);
if (mount("/proc", "/loopfs", "proc", 0, NULL))
printf("[] couldn't mount proc filesystem\n");
else {
int fd_cmdline = open("/loopfs/cmdline", O_RDONLY);
if (fd_cmdline > 0) {
i = read(fd_cmdline, buf, sizeof(buf));
if (i == -1)
warning("could not read cmdline");
else {
buf[i] = '\0';
if (strstr(buf, "quiet"))
quiet = 1;
}
close(fd_cmdline);
}
umount("/loopfs");
}
if (!quiet)
printf("[] initrd_helper v" VERSION "\n");
if ((fd_conf = open("/mkinitrd_helper.conf", O_RDONLY)) < 0)
fatal_error("could not open mkinitrd_helper config file");
i = read(fd_conf, buf, sizeof(buf));
if (i == -1)
fatal_error("could not read mkinitrd_helper config file");
buf[i] = '\0';
close(fd_conf);
ptr = buf;
while (*ptr)
if (!(handle_command(&ptr, "insmod", insmod_) +
handle_command(&ptr, "mount", mount_) +
handle_command(&ptr, "raidautorun", raidautorun_) +
handle_command(&ptr, "set_loop", set_loop_)))
warning("unkown command (trying to continue)");
return 0;
}

446
modules.c Normal file
View File

@ -0,0 +1,446 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* (1) calculate dependencies
* (2) unarchive relevant modules
* (3) insmod them
*/
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include "insmod.h"
#include "stage1.h"
#include "log.h"
#include "mar/mar-extract-only.h"
#include "frontend.h"
#include "mount.h"
#include "modules_descr.h"
#include "modules.h"
static struct module_deps_elem * modules_deps = NULL;
static char * archive_name = "/modules/modules.mar";
int disable_modules = 0;
/* unarchive and insmod given module
* WARNING: module must not contain the trailing ".o"
*/
static enum insmod_return insmod_archived_file(const char * mod_name, char * options)
{
char module_name[50];
char final_name[50] = "/tmp/";
int i, rc;
strncpy(module_name, mod_name, sizeof(module_name));
strcat(module_name, ".ko");
i = mar_extract_file(archive_name, module_name, "/tmp/");
if (i == 1) {
log_message("file-not-found-in-archive %s", module_name);
return INSMOD_FAILED_FILE_NOT_FOUND;
}
if (i != 0)
return INSMOD_FAILED;
strcat(final_name, mod_name);
strcat(final_name, ".ko");
rc = insmod_call(final_name, options);
unlink(final_name); /* sucking no space left on device */
if (rc) {
log_message("\tfailed");
return INSMOD_FAILED;
}
return INSMOD_OK;
}
static int load_modules_dependencies(void)
{
char * deps_file = "/modules/modules.dep";
char * buf, * ptr, * start, * end;
struct stat s;
int fd, line, i;
log_message("loading modules dependencies");
if (IS_TESTING)
return 0;
fd = open(deps_file, O_RDONLY);
if (fd == -1) {
log_perror(deps_file);
return -1;
}
fstat(fd, &s);
buf = alloca(s.st_size + 1);
if (read(fd, buf, s.st_size) != s.st_size) {
log_perror(deps_file);
return -1;
}
buf[s.st_size] = '\0';
close(fd);
ptr = buf;
line = 0;
while (ptr) {
line++;
ptr = strchr(ptr + 1, '\n');
}
modules_deps = malloc(sizeof(*modules_deps) * (line+1));
start = buf;
line = 0;
while (start < (buf+s.st_size) && *start) {
char * tmp_deps[50];
end = strchr(start, '\n');
*end = '\0';
ptr = strchr(start, ':');
if (!ptr) {
start = end + 1;
continue;
}
*ptr = '\0';
ptr++;
while (*ptr && (*ptr == ' ')) ptr++;
if (!*ptr) {
start = end + 1;
continue;
}
/* sort of a good line */
modules_deps[line].name = strdup(start);
start = ptr;
i = 0;
while (start && *start) {
ptr = strchr(start, ' ');
if (ptr) *ptr = '\0';
tmp_deps[i++] = strdup(start);
if (ptr)
start = ptr + 1;
else
start = NULL;
while (start && *start && *start == ' ')
start++;
}
tmp_deps[i++] = NULL;
modules_deps[line].deps = memdup(tmp_deps, sizeof(char *) * i);
line++;
start = end + 1;
}
modules_deps[line].name = NULL;
return 0;
}
void init_modules_insmoding(void)
{
if (load_modules_dependencies()) {
log_message("warning, error initing modules stuff, modules loading disabled");
disable_modules = 1;
}
}
static void add_modules_conf(char * str)
{
static char data[500] = "";
char * target = "/etc/modules.conf";
int fd;
if (strlen(data) + strlen(str) >= sizeof(data))
return;
strcat(data, str);
strcat(data, "\n");
fd = open(target, O_CREAT|O_WRONLY|O_TRUNC, 00660);
if (fd == -1) {
log_perror(str);
return;
}
if (write(fd, data, strlen(data) + 1) != strlen(data) + 1)
log_perror(str);
close(fd);
}
static int module_already_present(const char * name)
{
FILE * f;
int answ = 0;
f = fopen("/proc/modules", "rb");
while (1) {
char buf[500];
if (!fgets(buf, sizeof(buf), f)) break;
if (!strncmp(name, buf, strlen(name)) && buf[strlen(name)] == ' ')
answ = 1;
}
fclose(f);
return answ;
}
static enum insmod_return insmod_with_deps(const char * mod_name, char * options)
{
struct module_deps_elem * dep;
dep = modules_deps;
while (dep && dep->name && strcmp(dep->name, mod_name)) dep++;
if (dep && dep->name && dep->deps) {
char ** one_dep;
one_dep = dep->deps;
while (*one_dep) {
/* here, we can fail but we don't care, if the error is
* important, the desired module will fail also */
insmod_with_deps(*one_dep, NULL);
one_dep++;
}
}
if (module_already_present(mod_name))
return INSMOD_OK;
log_message("needs %s", mod_name);
return insmod_archived_file(mod_name, options);
}
enum insmod_return my_insmod(const char * mod_name, enum driver_type type, char * options)
{
char alias[500];
int i;
#ifndef DISABLE_MEDIAS
static int number_scsi = 0;
#endif
#ifndef DISABLE_NETWORK
char ** net_devices = NULL; /* fucking compiler */
#endif
log_message("have to insmod %s", mod_name);
if (disable_modules) {
log_message("\tdisabled");
return INSMOD_OK;
}
#ifndef DISABLE_NETWORK
if (type == NETWORK_DEVICES)
net_devices = get_net_devices();
#endif
if (IS_TESTING)
return INSMOD_OK;
i = insmod_with_deps(mod_name, options);
if (i == 0) {
log_message("\tsucceeded %s", mod_name);
#ifndef DISABLE_MEDIAS
if (type == SCSI_ADAPTERS) {
if (number_scsi > 0)
sprintf(alias, "alias scsi_hostadapter%d %s", number_scsi, mod_name);
else
sprintf(alias, "alias scsi_hostadapter %s", mod_name);
number_scsi++;
add_modules_conf(alias);
log_message("SCSI: %s", alias);
}
#endif
#ifndef DISABLE_NETWORK
if (type == NETWORK_DEVICES) {
char ** new_net_devices = get_net_devices();
while (new_net_devices && *new_net_devices) {
char ** ptr = net_devices;
while (ptr && *ptr) {
if (!strcmp(*new_net_devices, *ptr))
goto already_present;
ptr++;
}
sprintf(alias, "alias %s %s", *new_net_devices, mod_name);
add_modules_conf(alias);
log_message("NET: %s", alias);
net_discovered_interface(*new_net_devices);
already_present:
new_net_devices++;
}
}
#endif
} else
log_message("warning, insmod failed (%s %s) (%d)", mod_name, options, i);
return i;
}
static enum return_type insmod_with_options(char * mod, enum driver_type type)
{
char * questions[] = { "Options", NULL };
static char ** answers = NULL;
enum return_type results;
char options[500] = "options ";
results = ask_from_entries("Please enter the parameters to give to the kernel:", questions, &answers, 24, NULL);
if (results != RETURN_OK)
return results;
strcat(options, mod);
strcat(options, " ");
strcat(options, answers[0]); // because my_insmod will eventually modify the string
if (my_insmod(mod, type, answers[0]) != INSMOD_OK) {
stg1_error_message("Insmod failed.");
return RETURN_ERROR;
}
add_modules_conf(options);
return RETURN_OK;
}
enum return_type ask_insmod(enum driver_type type)
{
char * mytype;
char msg[200];
enum return_type results;
char * choice;
unset_param(MODE_AUTOMATIC); /* we are in a fallback mode */
if (type == SCSI_ADAPTERS)
mytype = "SCSI";
else if (type == NETWORK_DEVICES)
mytype = "NET";
else
return RETURN_ERROR;
if (disable_modules)
return RETURN_BACK;
snprintf(msg, sizeof(msg), "Which driver should I try to gain %s access?", mytype);
{
char ** drivers = mar_list_contents(archive_name);
char ** descrs = malloc(sizeof(char *) * string_array_length(drivers));
char ** p_drivers = drivers;
char ** p_descrs = descrs;
while (p_drivers && *p_drivers) {
int i;
*p_descrs = NULL;
for (i = 0 ; i < modules_descriptions_num ; i++) {
if (!strncmp(*p_drivers, modules_descriptions[i].module, strlen(modules_descriptions[i].module))
&& (*p_drivers)[strlen(modules_descriptions[i].module)] == '.') /* one contains '.o' not the other */
*p_descrs = modules_descriptions[i].descr;
}
p_drivers++;
p_descrs++;
}
results = ask_from_list_comments(msg, drivers, descrs, &choice);
}
if (results == RETURN_OK) {
choice[strlen(choice)-3] = '\0'; /* remove trailing .ko */
return insmod_with_options(choice, type);
} else
return results;
}
void update_modules(void)
{
FILE * f;
char ** disk_contents;
char final_name[500];
char floppy_mount_location[] = "/tmp/floppy";
stg1_info_message("Please insert the Update Modules floppy.");;
my_insmod("floppy", ANY_DRIVER_TYPE, NULL);
if (my_mount("/dev/fd0", floppy_mount_location, "ext2", 0) == -1) {
enum return_type results = ask_yes_no("I can't find a Linux ext2 floppy in first floppy drive.\n"
"Retry?");
if (results == RETURN_OK)
return update_modules();
return;
}
disk_contents = list_directory(floppy_mount_location);
if (!(f = fopen("/tmp/floppy/to_load", "rb"))) {
stg1_error_message("I can't find \"to_load\" file.");
umount(floppy_mount_location);
return update_modules();
}
while (1) {
char module[500];
char * options;
char ** entry = disk_contents;
if (!fgets(module, sizeof(module), f)) break;
if (module[0] == '#' || strlen(module) == 0)
continue;
while (module[strlen(module)-1] == '\n')
module[strlen(module)-1] = '\0';
options = strchr(module, ' ');
if (options) {
options[0] = '\0';
options++;
}
log_message("updatemodules: (%s) (%s)", module, options);
while (entry && *entry) {
if (!strncmp(*entry, module, strlen(module)) && (*entry)[strlen(module)] == '.') {
sprintf(final_name, "%s/%s", floppy_mount_location, *entry);
if (insmod_call(final_name, options)) {
log_message("\t%s (floppy): failed", *entry);
stg1_error_message("Insmod %s (floppy) failed.", *entry);
}
break;
}
entry++;
}
if (!entry || !*entry) {
enum insmod_return ret = my_insmod(module, ANY_DRIVER_TYPE, options);
if (ret != INSMOD_OK) {
log_message("\t%s (marfile): failed", module);
stg1_error_message("Insmod %s (marfile) failed.", module);
}
}
}
fclose(f);
}

35
modules.h Normal file
View File

@ -0,0 +1,35 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
#ifndef _MODULES_H_
#define _MODULES_H_
#include "stage1.h"
#include "probing.h"
enum insmod_return { INSMOD_OK, INSMOD_FAILED, INSMOD_FAILED_FILE_NOT_FOUND };
void init_modules_insmoding(void);
enum insmod_return my_insmod(const char * mod_name, enum driver_type type, char * options);
enum return_type ask_insmod(enum driver_type);
void update_modules(void);
struct module_deps_elem {
char * name;
char ** deps;
};
extern int disable_modules;
#endif

66
modules_descr.h Normal file
View File

@ -0,0 +1,66 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2001 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
#ifndef _MODULES_DESCR_H_
#define _MODULES_DESCR_H_
struct module_descr {
const char * module;
char * descr;
};
struct module_descr modules_descriptions[] = {
#ifndef DISABLE_NETWORK
/* description of network drivers that have not very explicit names */
{ "ne", "NE1000/NE2000/clones" },
{ "ne2k-pci", "PCI NE2000" },
{ "depca", "DEC DEPCA/DE100/DE101/DE200/DE201/DE202/DE210/DE422" },
{ "dgrs", "Digi RightSwitch SE-X" },
{ "ewrk3", "DEC DE203/DE204/DE205" },
{ "lance", "Allied Telesis AT1500, HP J2405A, NE2100/NE2500" },
{ "sis900", "SiS 900/7016/630E, Am79c901, RTL8201" },
{ "via-rhine", "VIA VT86c100A Rhine-II, 3043 Rhine-I" },
{ "tulip", "DEC 21040-family based cards" },
{ "wd", "WD8003/WD8013" },
{ "bmac", "Macintosh integrated ethernet (G3)" },
{ "gmac", "Macintosh integrated ethernet (G4/iBook)" },
{ "mace", "Macintosh integrated ethernet (PowerMac)" },
#endif
#ifndef DISABLE_MEDIAS
/* description of scsi drivers that have not very explicit names */
{ "53c7,8xx", "NCR53c810/700" },
{ "sim710", "NCR53c710" },
{ "aic7xxx", "Adaptec 7xxx family (AIC/AHA/etc)" },
{ "atp870u", "ACARD/ARTOP AEC-6710/6712" },
{ "ncr53c8xx", "Symbios 53c family" },
{ "sym53c8xx", "Symbios 53c family" },
{ "sim710", "NCR53C710 family" },
{ "mesh", "Macintosh integrated SCSI (NewWorld or internal SCSI)" },
{ "mac53c94", "Macintosh integrated SCSI (OldWorld or external SCSI)" },
#endif
#ifdef ENABLE_USB
/* description of usb drivers that have not very explicit names */
{ "usbnet", "Netchip or Prolific USB-USB Bridge" },
{ "pegasus", "ADMtek AN986 (USB Ethernet chipset)" },
{ "kaweth", "KL5KUSB101 (USB Ethernet chipset)" },
{ "catc", "CATC EL1210A NetMate USB Ethernet" },
#endif
};
int modules_descriptions_num = sizeof(modules_descriptions) / sizeof(struct module_descr);
#endif

188
mount.c Normal file
View File

@ -0,0 +1,188 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "log.h"
#include "modules.h"
#include "mount.h"
#ifndef DISABLE_MEDIAS
/* WARNING: this won't work if the argument is not /dev/ based */
int ensure_dev_exists(char *dev)
{
int major, minor;
int type = S_IFBLK; /* my default type is block. don't forget to change for chars */
char * name;
struct stat buf;
char * ptr;
name = &dev[5]; /* we really need that dev be passed as /dev/something.. */
if (!stat(dev, &buf))
return 0; /* if the file already exists, we assume it's correct */
if (name[0] == 's' && name[1] == 'd') {
/* SCSI disks */
major = 8;
minor = (name[2] - 'a') << 4;
if (name[3] && name[4])
minor += 10 + (name[4] - '0');
else if (name[3])
minor += (name[3] - '0');
} else if (name[0] == 'h' && name[1] == 'd') {
/* IDE disks/cd's */
if (name[2] == 'a')
major = 3, minor = 0;
else if (name[2] == 'b')
major = 3, minor = 64;
else if (name[2] == 'c')
major = 22, minor = 0;
else if (name[2] == 'd')
major = 22, minor = 64;
else if (name[2] == 'e')
major = 33, minor = 0;
else if (name[2] == 'f')
major = 33, minor = 64;
else if (name[2] == 'g')
major = 34, minor = 0;
else if (name[2] == 'h')
major = 34, minor = 64;
else
return -1;
if (name[3] && name[4])
minor += 10 + (name[4] - '0');
else if (name[3])
minor += (name[3] - '0');
} else if (name[0] == 's' && name[1] == 'r') {
/* SCSI cd's */
major = 11;
minor = name[2] - '0';
} else if (ptr_begins_static_str(name, "ida/") ||
ptr_begins_static_str(name, "cciss/")) {
/* Compaq Smart Array "ida/c0d0{p1}" */
ptr = strchr(name, '/');
mkdir("/dev/ida", 0755);
mkdir("/dev/cciss", 0755);
major = ptr_begins_static_str(name, "ida/") ? 72 : 104 + charstar_to_int(ptr+2);
ptr = strchr(ptr, 'd');
minor = 16 * charstar_to_int(ptr+1);
ptr = strchr(ptr, 'p');
minor += charstar_to_int(ptr+1);
} else if (ptr_begins_static_str(name, "rd/")) {
/* DAC960 "rd/cXdXXpX" */
mkdir("/dev/rd", 0755);
major = 48 + charstar_to_int(name+4);
ptr = strchr(name+4, 'd');
minor = 8 * charstar_to_int(ptr+1);
ptr = strchr(ptr, 'p');
minor += charstar_to_int(ptr+1);
} else {
log_message("I don't know how to create device %s, please post bugreport to me!", dev);
return -1;
}
if (mknod(dev, type | 0600, makedev(major, minor))) {
log_perror(dev);
return -1;
}
return 0;
}
#endif /* DISABLE_MEDIAS */
/* mounts, creating the device if needed+possible */
int my_mount(char *dev, char *location, char *fs, int force_rw)
{
unsigned long flags = MS_MGC_VAL | (force_rw ? 0 : MS_RDONLY);
char * opts = NULL;
struct stat buf;
int rc;
#ifndef DISABLE_MEDIAS
if (strcmp(fs, "nfs")) {
rc = ensure_dev_exists(dev);
if (rc != 0) {
log_message("could not create required device file");
return -1;
}
}
#endif
log_message("mounting %s on %s as type %s", dev, location, fs);
if (stat(location, &buf)) {
if (mkdir(location, 0755)) {
log_perror("could not create location dir");
return -1;
}
} else if (!S_ISDIR(buf.st_mode)) {
log_message("not a dir %s, will unlink and mkdir", location);
if (unlink(location)) {
log_perror("could not unlink");
return -1;
}
if (mkdir(location, 0755)) {
log_perror("could not create location dir");
return -1;
}
}
#ifndef DISABLE_MEDIAS
if (!strcmp(fs, "vfat")) {
my_insmod("vfat", ANY_DRIVER_TYPE, NULL);
opts = "check=relaxed";
}
if (!strcmp(fs, "reiserfs"))
my_insmod("reiserfs", ANY_DRIVER_TYPE, NULL);
if (!strcmp(fs, "iso9660"))
my_insmod("isofs", ANY_DRIVER_TYPE, NULL);
#endif
#ifndef DISABLE_NETWORK
if (!strcmp(fs, "nfs")) {
my_insmod("nfs", ANY_DRIVER_TYPE, NULL);
log_message("preparing nfsmount for %s", dev);
rc = nfsmount_prepare(dev, &opts);
if (rc != 0)
return rc;
}
#endif
rc = mount(dev, location, fs, flags, opts);
if (rc != 0) {
log_perror("mount failed");
rmdir(location);
}
return rc;
}

35
mount.h Normal file
View File

@ -0,0 +1,35 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#ifndef _MOUNT_H_
#define _MOUNT_H_
#ifndef DISABLE_NETWORK
#include "nfsmount.h"
#endif
int my_mount(char *dev, char *location, char *fs, int force_rw);
#ifndef DISABLE_MEDIAS
int ensure_dev_exists(char *dev);
#endif
#endif

208
mount_rpcgen.h Normal file
View File

@ -0,0 +1,208 @@
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#ifndef _MOUNT_H_RPCGEN
#define _MOUNT_H_RPCGEN
#include <rpc/rpc.h>
#define MNTPATHLEN 1024
#define MNTNAMLEN 255
#define FHSIZE 32
typedef char fhandle[FHSIZE];
#ifdef __cplusplus
extern "C" bool_t xdr_fhandle(XDR *, fhandle);
#elif __STDC__
extern bool_t xdr_fhandle(XDR *, fhandle);
#else /* Old Style C */
bool_t xdr_fhandle();
#endif /* Old Style C */
struct fhstatus {
u_int fhs_status;
union {
fhandle fhs_fhandle;
} fhstatus_u;
};
typedef struct fhstatus fhstatus;
#ifdef __cplusplus
extern "C" bool_t xdr_fhstatus(XDR *, fhstatus*);
#elif __STDC__
extern bool_t xdr_fhstatus(XDR *, fhstatus*);
#else /* Old Style C */
bool_t xdr_fhstatus();
#endif /* Old Style C */
typedef char *dirpath;
#ifdef __cplusplus
extern "C" bool_t xdr_dirpath(XDR *, dirpath*);
#elif __STDC__
extern bool_t xdr_dirpath(XDR *, dirpath*);
#else /* Old Style C */
bool_t xdr_dirpath();
#endif /* Old Style C */
typedef char *name;
#ifdef __cplusplus
extern "C" bool_t xdr_name(XDR *, name*);
#elif __STDC__
extern bool_t xdr_name(XDR *, name*);
#else /* Old Style C */
bool_t xdr_name();
#endif /* Old Style C */
typedef struct mountbody *mountlist;
#ifdef __cplusplus
extern "C" bool_t xdr_mountlist(XDR *, mountlist*);
#elif __STDC__
extern bool_t xdr_mountlist(XDR *, mountlist*);
#else /* Old Style C */
bool_t xdr_mountlist();
#endif /* Old Style C */
struct mountbody {
name ml_hostname;
dirpath ml_directory;
mountlist ml_next;
};
typedef struct mountbody mountbody;
#ifdef __cplusplus
extern "C" bool_t xdr_mountbody(XDR *, mountbody*);
#elif __STDC__
extern bool_t xdr_mountbody(XDR *, mountbody*);
#else /* Old Style C */
bool_t xdr_mountbody();
#endif /* Old Style C */
typedef struct groupnode *groups;
#ifdef __cplusplus
extern "C" bool_t xdr_groups(XDR *, groups*);
#elif __STDC__
extern bool_t xdr_groups(XDR *, groups*);
#else /* Old Style C */
bool_t xdr_groups();
#endif /* Old Style C */
struct groupnode {
name gr_name;
groups gr_next;
};
typedef struct groupnode groupnode;
#ifdef __cplusplus
extern "C" bool_t xdr_groupnode(XDR *, groupnode*);
#elif __STDC__
extern bool_t xdr_groupnode(XDR *, groupnode*);
#else /* Old Style C */
bool_t xdr_groupnode();
#endif /* Old Style C */
typedef struct exportnode *exports;
#ifdef __cplusplus
extern "C" bool_t xdr_exports(XDR *, exports*);
#elif __STDC__
extern bool_t xdr_exports(XDR *, exports*);
#else /* Old Style C */
bool_t xdr_exports();
#endif /* Old Style C */
struct exportnode {
dirpath ex_dir;
groups ex_groups;
exports ex_next;
};
typedef struct exportnode exportnode;
#ifdef __cplusplus
extern "C" bool_t xdr_exportnode(XDR *, exportnode*);
#elif __STDC__
extern bool_t xdr_exportnode(XDR *, exportnode*);
#else /* Old Style C */
bool_t xdr_exportnode();
#endif /* Old Style C */
#define MOUNTPROG ((u_long)100005)
#define MOUNTVERS ((u_long)1)
#ifdef __cplusplus
#define MOUNTPROC_NULL ((u_long)0)
extern "C" void * mountproc_null_1(void *, CLIENT *);
extern "C" void * mountproc_null_1_svc(void *, struct svc_req *);
#define MOUNTPROC_MNT ((u_long)1)
extern "C" fhstatus * mountproc_mnt_1(dirpath *, CLIENT *);
extern "C" fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *);
#define MOUNTPROC_DUMP ((u_long)2)
extern "C" mountlist * mountproc_dump_1(void *, CLIENT *);
extern "C" mountlist * mountproc_dump_1_svc(void *, struct svc_req *);
#define MOUNTPROC_UMNT ((u_long)3)
extern "C" void * mountproc_umnt_1(dirpath *, CLIENT *);
extern "C" void * mountproc_umnt_1_svc(dirpath *, struct svc_req *);
#define MOUNTPROC_UMNTALL ((u_long)4)
extern "C" void * mountproc_umntall_1(void *, CLIENT *);
extern "C" void * mountproc_umntall_1_svc(void *, struct svc_req *);
#define MOUNTPROC_EXPORT ((u_long)5)
extern "C" exports * mountproc_export_1(void *, CLIENT *);
extern "C" exports * mountproc_export_1_svc(void *, struct svc_req *);
#define MOUNTPROC_EXPORTALL ((u_long)6)
extern "C" exports * mountproc_exportall_1(void *, CLIENT *);
extern "C" exports * mountproc_exportall_1_svc(void *, struct svc_req *);
#elif __STDC__
#define MOUNTPROC_NULL ((u_long)0)
extern void * mountproc_null_1(void *, CLIENT *);
extern void * mountproc_null_1_svc(void *, struct svc_req *);
#define MOUNTPROC_MNT ((u_long)1)
extern fhstatus * mountproc_mnt_1(dirpath *, CLIENT *);
extern fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *);
#define MOUNTPROC_DUMP ((u_long)2)
extern mountlist * mountproc_dump_1(void *, CLIENT *);
extern mountlist * mountproc_dump_1_svc(void *, struct svc_req *);
#define MOUNTPROC_UMNT ((u_long)3)
extern void * mountproc_umnt_1(dirpath *, CLIENT *);
extern void * mountproc_umnt_1_svc(dirpath *, struct svc_req *);
#define MOUNTPROC_UMNTALL ((u_long)4)
extern void * mountproc_umntall_1(void *, CLIENT *);
extern void * mountproc_umntall_1_svc(void *, struct svc_req *);
#define MOUNTPROC_EXPORT ((u_long)5)
extern exports * mountproc_export_1(void *, CLIENT *);
extern exports * mountproc_export_1_svc(void *, struct svc_req *);
#define MOUNTPROC_EXPORTALL ((u_long)6)
extern exports * mountproc_exportall_1(void *, CLIENT *);
extern exports * mountproc_exportall_1_svc(void *, struct svc_req *);
#else /* Old Style C */
#define MOUNTPROC_NULL ((u_long)0)
extern void * mountproc_null_1();
extern void * mountproc_null_1_svc();
#define MOUNTPROC_MNT ((u_long)1)
extern fhstatus * mountproc_mnt_1();
extern fhstatus * mountproc_mnt_1_svc();
#define MOUNTPROC_DUMP ((u_long)2)
extern mountlist * mountproc_dump_1();
extern mountlist * mountproc_dump_1_svc();
#define MOUNTPROC_UMNT ((u_long)3)
extern void * mountproc_umnt_1();
extern void * mountproc_umnt_1_svc();
#define MOUNTPROC_UMNTALL ((u_long)4)
extern void * mountproc_umntall_1();
extern void * mountproc_umntall_1_svc();
#define MOUNTPROC_EXPORT ((u_long)5)
extern exports * mountproc_export_1();
extern exports * mountproc_export_1_svc();
#define MOUNTPROC_EXPORTALL ((u_long)6)
extern exports * mountproc_exportall_1();
extern exports * mountproc_exportall_1_svc();
#endif /* Old Style C */
#endif /* !_MOUNT_H_RPCGEN */

830
network.c Normal file
View File

@ -0,0 +1,830 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
// #include <sys/socket.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <net/route.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <stdio.h>
#include <netdb.h>
#include <resolv.h>
#include "stage1.h"
#include "frontend.h"
#include "modules.h"
#include "probing.h"
#include "log.h"
#include "mount.h"
#include "automatic.h"
#include "dhcp.h"
#include "adsl.h"
#include "url.h"
#include "dns.h"
#include "network.h"
static void error_message_net(void) /* reduce code size */
{
stg1_error_message("Could not configure network.");
}
int configure_net_device(struct interface_info * intf)
{
struct ifreq req;
struct rtentry route;
int s;
struct sockaddr_in addr;
struct in_addr ia;
char ip[20], nm[20], nw[20], bc[20];
addr.sin_family = AF_INET;
addr.sin_port = 0;
memcpy(&ia, &intf->ip, sizeof(intf->ip));
strcpy(ip, inet_ntoa(ia));
memcpy(&ia, &intf->netmask, sizeof(intf->netmask));
strcpy(nm, inet_ntoa(ia));
memcpy(&ia, &intf->broadcast, sizeof(intf->broadcast));
strcpy(bc, inet_ntoa(ia));
memcpy(&ia, &intf->network, sizeof(intf->network));
strcpy(nw, inet_ntoa(ia));
log_message("configuring device %s ip: %s nm: %s nw: %s bc: %s", intf->device, ip, nm, nw, bc);
if (IS_TESTING)
return 0;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
log_perror("socket");
error_message_net();
return 1;
}
strcpy(req.ifr_name, intf->device);
if (intf->is_up == 1) {
log_message("interface already up, downing before reconfigure");
req.ifr_flags = 0;
if (ioctl(s, SIOCSIFFLAGS, &req)) {
close(s);
log_perror("SIOCSIFFLAGS (downing)");
error_message_net();
return 1;
}
}
/* sets IP address */
addr.sin_port = 0;
memcpy(&addr.sin_addr, &intf->ip, sizeof(intf->ip));
memcpy(&req.ifr_addr, &addr, sizeof(addr));
if (ioctl(s, SIOCSIFADDR, &req)) {
close(s);
log_perror("SIOCSIFADDR");
error_message_net();
return 1;
}
/* sets broadcast */
memcpy(&addr.sin_addr, &intf->broadcast, sizeof(intf->broadcast));
memcpy(&req.ifr_broadaddr, &addr, sizeof(addr));
if (ioctl(s, SIOCSIFBRDADDR, &req)) {
close(s);
log_perror("SIOCSIFBRDADDR");
error_message_net();
return 1;
}
/* sets netmask */
memcpy(&addr.sin_addr, &intf->netmask, sizeof(intf->netmask));
memcpy(&req.ifr_netmask, &addr, sizeof(addr));
if (ioctl(s, SIOCSIFNETMASK, &req)) {
close(s);
log_perror("SIOCSIFNETMASK");
error_message_net();
return 1;
}
if (intf->is_ptp)
req.ifr_flags = IFF_UP | IFF_RUNNING | IFF_POINTOPOINT | IFF_NOARP;
else
req.ifr_flags = IFF_UP | IFF_RUNNING | IFF_BROADCAST;
/* brings up networking! */
if (ioctl(s, SIOCSIFFLAGS, &req)) {
close(s);
log_perror("SIOCSIFFLAGS (upping)");
error_message_net();
return 1;
}
memset(&route, 0, sizeof(route));
route.rt_dev = intf->device;
route.rt_flags = RTF_UP;
memcpy(&addr.sin_addr, &intf->network, sizeof(intf->network));
memcpy(&route.rt_dst, &addr, sizeof(addr));
memcpy(&addr.sin_addr, &intf->netmask, sizeof(intf->netmask));
memcpy(&route.rt_genmask, &addr, sizeof(addr));
/* adds route */
if (ioctl(s, SIOCADDRT, &route)) {
close(s);
log_perror("SIOCADDRT");
error_message_net();
return 1;
}
close(s);
intf->is_up = 1;
if (intf->boot_proto != BOOTPROTO_DHCP && !streq(intf->device, "lo")) {
/* I need to sleep a bit in order for kernel to finish
init of the network device; if not, first sendto() for
gethostbyaddr will get an EINVAL. */
wait_message("Bringing up networking...");
sleep(2);
remove_wait_message();
}
return 0;
}
/* host network informations */
char * hostname = NULL;
char * domain = NULL;
struct in_addr gateway = { 0 };
struct in_addr dns_server = { 0 };
struct in_addr dns_server2 = { 0 };
static int add_default_route(void)
{
int s;
struct rtentry route;
struct sockaddr_in addr;
if (IS_TESTING)
return 0;
if (gateway.s_addr == 0) {
log_message("no gateway provided, can't add default route");
return 0;
}
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
close(s);
log_perror("socket");
error_message_net();
return 1;
}
memset(&route, 0, sizeof(route));
addr.sin_family = AF_INET;
addr.sin_port = 0;
addr.sin_addr = gateway;
memcpy(&route.rt_gateway, &addr, sizeof(addr));
addr.sin_addr.s_addr = INADDR_ANY;
memcpy(&route.rt_dst, &addr, sizeof(addr));
memcpy(&route.rt_genmask, &addr, sizeof(addr));
route.rt_flags = RTF_UP | RTF_GATEWAY;
route.rt_metric = 0;
if (ioctl(s, SIOCADDRT, &route)) {
close(s);
log_perror("SIOCADDRT");
error_message_net();
return 1;
}
close(s);
return 0;
}
static int write_resolvconf(void) {
char * filename = "/etc/resolv.conf";
FILE * f;
if (dns_server.s_addr == 0) {
log_message("resolvconf needs a dns server");
return -1;
}
f = fopen(filename, "w");
if (!f) {
log_perror(filename);
return -1;
}
if (domain)
fprintf(f, "search %s\n", domain); /* we can live without the domain search (user will have to enter fully-qualified names) */
fprintf(f, "nameserver %s\n", inet_ntoa(dns_server));
if (dns_server2.s_addr != 0)
fprintf(f, "nameserver %s\n", inet_ntoa(dns_server2));
fclose(f);
res_init(); /* reinit the resolver so DNS changes take affect */
return 0;
}
static int save_netinfo(struct interface_info * intf) {
char * file_network = "/tmp/network";
char file_intf[500];
FILE * f;
f = fopen(file_network, "w");
if (!f) {
log_perror(file_network);
return -1;
}
fprintf(f, "NETWORKING=yes\n");
fprintf(f, "FORWARD_IPV4=false\n");
if (hostname)
fprintf(f, "HOSTNAME=%s\n", hostname);
if (domain)
fprintf(f, "DOMAINNAME=%s\n", domain);
if (gateway.s_addr != 0)
fprintf(f, "GATEWAY=%s\n", inet_ntoa(gateway));
fclose(f);
strcpy(file_intf, "/tmp/ifcfg-");
strcat(file_intf, intf->device);
f = fopen(file_intf, "w");
if (!f) {
log_perror(file_intf);
return -1;
}
fprintf(f, "DEVICE=%s\n", intf->device);
if (intf->boot_proto == BOOTPROTO_DHCP)
fprintf(f, "BOOTPROTO=dhcp\n");
else if (intf->boot_proto == BOOTPROTO_STATIC) {
fprintf(f, "BOOTPROTO=static\n");
fprintf(f, "IPADDR=%s\n", inet_ntoa(intf->ip));
fprintf(f, "NETMASK=%s\n", inet_ntoa(intf->netmask));
fprintf(f, "NETWORK=%s\n", inet_ntoa(intf->network));
fprintf(f, "BROADCAST=%s\n", inet_ntoa(intf->broadcast));
} else if (intf->boot_proto == BOOTPROTO_ADSL_PPPOE) {
fprintf(f, "BOOTPROTO=adsl_pppoe\n");
fprintf(f, "USER=%s\n", intf->user);
fprintf(f, "PASS=%s\n", intf->pass);
}
fclose(f);
return 0;
}
char * guess_netmask(char * ip_addr)
{
struct in_addr addr;
unsigned long int tmp;
if (streq(ip_addr, "") || !inet_aton(ip_addr, &addr))
return "";
log_message("guessing netmask");
tmp = ntohl(addr.s_addr);
if (((tmp & 0xFF000000) >> 24) <= 127)
return "255.0.0.0";
else if (((tmp & 0xFF000000) >> 24) <= 191)
return "255.255.0.0";
else
return "255.255.255.0";
}
static void static_ip_callback(char ** strings)
{
struct in_addr addr;
if (!inet_aton(strings[0], &addr))
return;
if (!strcmp(strings[1], "")) {
char * ptr;
strings[1] = strdup(strings[0]);
ptr = strrchr(strings[1], '.');
if (ptr)
*(ptr+1) = '\0';
}
if (!strcmp(strings[2], ""))
strings[2] = strdup(strings[1]);
if (!strcmp(strings[3], ""))
strings[3] = strdup(guess_netmask(strings[0]));
}
static enum return_type setup_network_interface(struct interface_info * intf)
{
enum return_type results;
char * bootprotos[] = { "Static", "DHCP", "ADSL", NULL };
char * bootprotos_auto[] = { "static", "dhcp", "adsl" };
char * choice;
results = ask_from_list_auto("Please choose the desired IP attribution.", bootprotos, &choice, "network", bootprotos_auto);
if (results != RETURN_OK)
return results;
if (!strcmp(choice, "Static")) {
char * questions[] = { "IP of this machine", "IP of DNS", "IP of default gateway", "Netmask", NULL };
char * questions_auto[] = { "ip", "dns", "gateway", "netmask" };
static char ** answers = NULL;
struct in_addr addr;
results = ask_from_entries_auto("Please enter the network information. (leave netmask void for Internet standard)",
questions, &answers, 16, questions_auto, static_ip_callback);
if (results != RETURN_OK)
return setup_network_interface(intf);
if (streq(answers[0], "") || !inet_aton(answers[0], &addr)) {
stg1_error_message("Invalid IP address.");
return setup_network_interface(intf);
}
memcpy(&intf->ip, &addr, sizeof(addr));
if (!inet_aton(answers[1], &dns_server)) {
log_message("invalid DNS");
dns_server.s_addr = 0; /* keep an understandable state */
}
if (!inet_aton(answers[2], &gateway)) {
log_message("invalid gateway");
gateway.s_addr = 0; /* keep an understandable state */
}
if ((streq(answers[3], "") && inet_aton(guess_netmask(answers[0]), &addr))
|| inet_aton(answers[3], &addr))
memcpy(&intf->netmask, &addr, sizeof(addr));
else {
stg1_error_message("Invalid netmask.");
return setup_network_interface(intf);
}
*((uint32_t *) &intf->broadcast) = (*((uint32_t *) &intf->ip) &
*((uint32_t *) &intf->netmask)) | ~(*((uint32_t *) &intf->netmask));
inet_aton("255.255.255.255", &addr);
if (!memcmp(&addr, &intf->netmask, sizeof(addr))) {
log_message("netmask is 255.255.255.255 -> point to point device");
intf->network = gateway;
intf->is_ptp = 1;
} else {
*((uint32_t *) &intf->network) = *((uint32_t *) &intf->ip) & *((uint32_t *) &intf->netmask);
intf->is_ptp = 0;
}
intf->boot_proto = BOOTPROTO_STATIC;
if (configure_net_device(intf))
return RETURN_ERROR;
} else if (streq(choice, "DHCP")) {
results = perform_dhcp(intf);
if (results == RETURN_BACK)
return setup_network_interface(intf);
if (results == RETURN_ERROR)
return results;
intf->boot_proto = BOOTPROTO_DHCP;
if (configure_net_device(intf))
return RETURN_ERROR;
} else if (streq(choice, "ADSL")) {
results = perform_adsl(intf);
if (results == RETURN_BACK)
return setup_network_interface(intf);
if (results == RETURN_ERROR)
return results;
} else
return RETURN_ERROR;
return add_default_route();
}
static enum return_type configure_network(struct interface_info * intf)
{
char * dnshostname;
if (hostname && domain)
return RETURN_OK;
dnshostname = mygethostbyaddr(inet_ntoa(intf->ip));
if (dnshostname) {
hostname = strdup(dnshostname);
domain = strchr(strdup(hostname), '.') + 1;
log_message("got hostname and domain from dns entry, %s and %s", hostname, domain);
return RETURN_OK;
}
log_message("reverse name lookup on self failed");
if (domain)
return RETURN_OK;
if (dns_server.s_addr != 0) {
wait_message("Trying to resolve dns...");
dnshostname = mygethostbyaddr(inet_ntoa(dns_server));
remove_wait_message();
}
if (dnshostname) {
domain = strchr(strdup(dnshostname), '.') + 1;
log_message("got domain from DNS fullname, %s", domain);
} else {
enum return_type results;
char * questions[] = { "Host name", "Domain name", NULL };
char * questions_auto[] = { "hostname", "domain" };
static char ** answers = NULL;
char * boulet;
log_message("reverse name lookup on DNS failed");
results = ask_from_entries_auto("I could not guess hostname and domain name; please fill in this information. "
"Valid answers are for example: `mybox' for hostname and `mynetwork.com' for "
"domain name, for a machine called `mybox.mynetwork.com' on the Internet.",
questions, &answers, 32, questions_auto, NULL);
if (results != RETURN_OK)
return results;
hostname = answers[0];
if ((boulet = strchr(hostname, '.')) != NULL)
boulet[0] = '\0';
domain = answers[1];
}
return RETURN_OK;
}
static enum return_type bringup_networking(struct interface_info * intf)
{
static struct interface_info loopback;
enum return_type results = RETURN_ERROR;
my_insmod("af_packet", ANY_DRIVER_TYPE, NULL);
while (results != RETURN_OK) {
results = setup_network_interface(intf);
if (results != RETURN_OK)
return results;
write_resolvconf();
results = configure_network(intf);
}
write_resolvconf(); /* maybe we have now domain to write also */
if (loopback.is_up == 0) {
int rc;
strcpy(loopback.device, "lo");
loopback.is_ptp = 0;
loopback.is_up = 0;
loopback.ip.s_addr = htonl(0x7f000001);
loopback.netmask.s_addr = htonl(0xff000000);
loopback.broadcast.s_addr = htonl(0x7fffffff);
loopback.network.s_addr = htonl(0x7f000000);
rc = configure_net_device(&loopback);
if (rc)
return RETURN_ERROR;
}
return RETURN_OK;
}
static char * interface_select(void)
{
char ** interfaces, ** ptr;
char * descriptions[50];
char * choice;
int i, count = 0;
enum return_type results;
interfaces = get_net_devices();
ptr = interfaces;
while (ptr && *ptr) {
count++;
ptr++;
}
if (count == 0) {
stg1_error_message("No NET device found.");
i = ask_insmod(NETWORK_DEVICES);
if (i == RETURN_BACK)
return NULL;
return interface_select();
}
if (count == 1)
return *interfaces;
i = 0;
while (interfaces[i]) {
descriptions[i] = get_net_intf_description(interfaces[i]);
i++;
}
results = ask_from_list_comments_auto("Please choose the NET device to use for the installation.",
interfaces, descriptions, &choice, "interface", interfaces);
if (results != RETURN_OK)
return NULL;
return choice;
}
/* -=-=-- */
static enum return_type intf_select_and_up(void)
{
static struct interface_info intf[20];
static int num_interfaces = 0;
struct interface_info * sel_intf = NULL;
int i;
enum return_type results;
char * iface = interface_select();
if (iface == NULL)
return RETURN_BACK;
for (i = 0; i < num_interfaces ; i++)
if (!strcmp(intf[i].device, iface))
sel_intf = &(intf[i]);
if (sel_intf == NULL) {
sel_intf = &(intf[num_interfaces]);
strcpy(sel_intf->device, iface);
sel_intf->is_up = 0;
num_interfaces++;
}
results = bringup_networking(sel_intf);
if (results == RETURN_OK)
save_netinfo(sel_intf);
return results;
}
enum return_type nfs_prepare(void)
{
char * questions[] = { "NFS server name", DISTRIB_NAME " directory", NULL };
char * questions_auto[] = { "server", "directory", NULL };
static char ** answers = NULL;
char * nfsmount_location;
enum return_type results = intf_select_and_up();
if (results != RETURN_OK)
return results;
do {
results = ask_from_entries_auto("Please enter the name or IP address of your NFS server, "
"and the directory containing the " DISTRIB_NAME " Distribution.",
questions, &answers, 40, questions_auto, NULL);
if (results != RETURN_OK || streq(answers[0], "")) {
unset_param(MODE_AUTOMATIC); /* we are in a fallback mode */
return nfs_prepare();
}
nfsmount_location = malloc(strlen(answers[0]) + strlen(answers[1]) + 2);
strcpy(nfsmount_location, answers[0]);
strcat(nfsmount_location, ":");
strcat(nfsmount_location, answers[1]);
if (my_mount(nfsmount_location, IMAGE_LOCATION, "nfs", 0) == -1) {
stg1_error_message("I can't mount the directory from the NFS server.");
results = RETURN_BACK;
continue;
}
if (access(IMAGE_LOCATION LIVE_LOCATION, R_OK)) {
stg1_error_message("That NFS volume does not seem to contain the " DISTRIB_NAME " Distribution.");
umount(IMAGE_LOCATION);
results = RETURN_BACK;
}
}
while (results == RETURN_BACK);
log_message("found the " DISTRIB_NAME " Installation, good news!");
if (IS_SPECIAL_STAGE2) {
if (load_ramdisk() != RETURN_OK) {
stg1_error_message("Could not load program into memory.");
return nfs_prepare();
}
}
if (IS_RESCUE)
umount(IMAGE_LOCATION);
method_name = strdup("nfs");
return RETURN_OK;
}
enum return_type ftp_prepare(void)
{
char * questions[] = { "FTP server", DISTRIB_NAME " directory", "Login", "Password", NULL };
char * questions_auto[] = { "server", "directory", "user", "pass", NULL };
static char ** answers = NULL;
enum return_type results;
if (!ramdisk_possible()) {
stg1_error_message("FTP install needs more than %d Mbytes of memory (detected %d Mbytes).",
MEM_LIMIT_RAMDISK, total_memory());
return RETURN_ERROR;
}
results = intf_select_and_up();
if (results != RETURN_OK)
return results;
do {
char location_full[500];
int ftp_serv_response;
int fd, size;
results = ask_from_entries_auto("Please enter the name or IP address of the FTP server, "
"the directory containing the " DISTRIB_NAME " Distribution, "
"and the login/pass if necessary (leave login blank for anonymous).",
questions, &answers, 40, questions_auto, NULL);
if (results != RETURN_OK || streq(answers[0], "")) {
unset_param(MODE_AUTOMATIC); /* we are in a fallback mode */
return ftp_prepare();
}
log_message("FTP: trying to connect to %s", answers[0]);
ftp_serv_response = ftp_open_connection(answers[0], answers[2], answers[3], "");
if (ftp_serv_response < 0) {
log_message("FTP: error connect %d", ftp_serv_response);
if (ftp_serv_response == FTPERR_BAD_HOSTNAME)
stg1_error_message("Error: bad hostname.");
else if (ftp_serv_response == FTPERR_FAILED_CONNECT)
stg1_error_message("Error: failed to connect to remote host.");
else
stg1_error_message("Error: couldn't connect.");
results = RETURN_BACK;
continue;
}
strcpy(location_full, answers[1]);
strcat(location_full, get_ramdisk_realname());
log_message("FTP: trying to retrieve %s", location_full);
fd = ftp_start_download(ftp_serv_response, location_full, &size);
if (fd < 0) {
log_message("FTP: error get %d", fd);
if (fd == FTPERR_PASSIVE_ERROR)
stg1_error_message("Error: error with passive connection.");
else if (fd == FTPERR_FILE_NOT_FOUND)
stg1_error_message("Error: file not found (%s).", location_full);
else if (fd == FTPERR_BAD_SERVER_RESPONSE)
stg1_error_message("Error: bad server response (server too busy?).");
else
stg1_error_message("Error: couldn't retrieve Installation program.");
results = RETURN_BACK;
continue;
}
log_message("FTP: size of download %d bytes", size);
results = load_ramdisk_fd(fd, size);
if (results == RETURN_OK)
ftp_end_data_command(ftp_serv_response);
else
return results;
method_name = strdup("ftp");
add_to_env("HOST", answers[0]);
add_to_env("PREFIX", answers[1]);
if (strcmp(answers[2], "")) {
add_to_env("LOGIN", answers[2]);
add_to_env("PASSWORD", answers[3]);
}
}
while (results == RETURN_BACK);
return RETURN_OK;
}
enum return_type http_prepare(void)
{
char * questions[] = { "HTTP server", DISTRIB_NAME " directory", NULL };
char * questions_auto[] = { "server", "directory", NULL };
static char ** answers = NULL;
enum return_type results;
if (!ramdisk_possible()) {
stg1_error_message("HTTP install needs more than %d Mbytes of memory (detected %d Mbytes).",
MEM_LIMIT_RAMDISK, total_memory());
return RETURN_ERROR;
}
results = intf_select_and_up();
if (results != RETURN_OK)
return results;
do {
char location_full[500];
int fd, size;
results = ask_from_entries_auto("Please enter the name or IP address of the HTTP server, "
"and the directory containing the " DISTRIB_NAME " Distribution.",
questions, &answers, 40, questions_auto, NULL);
if (results != RETURN_OK || streq(answers[0], "")) {
unset_param(MODE_AUTOMATIC); /* we are in a fallback mode */
return http_prepare();
}
strcpy(location_full, answers[1]);
strcat(location_full, get_ramdisk_realname());
log_message("HTTP: trying to retrieve %s", location_full);
fd = http_download_file(answers[0], location_full, &size);
if (fd < 0) {
log_message("HTTP: error %d", fd);
if (fd == FTPERR_FAILED_CONNECT)
stg1_error_message("Error: couldn't connect to server.");
else
stg1_error_message("Error: couldn't get file (%s).", location_full);
results = RETURN_BACK;
continue;
}
log_message("HTTP: size of download %d bytes", size);
if (load_ramdisk_fd(fd, size) != RETURN_OK)
return RETURN_ERROR;
method_name = strdup("http");
sprintf(location_full, "http://%s/%s", answers[0], answers[1]);
add_to_env("URLPREFIX", location_full);
}
while (results == RETURN_BACK);
return RETURN_OK;
}

61
network.h Normal file
View File

@ -0,0 +1,61 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#ifndef _NETWORK_H_
#define _NETWORK_H_
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
enum return_type nfs_prepare(void);
enum return_type ftp_prepare(void);
enum return_type http_prepare(void);
enum boot_proto_type { BOOTPROTO_STATIC, BOOTPROTO_DHCP, BOOTPROTO_ADSL_PPPOE };
/* all of these in_addr things are in network byte order! */
struct interface_info {
char device[10];
int is_ptp, is_up;
struct in_addr ip, netmask, broadcast, network;
enum boot_proto_type boot_proto;
char *user, *pass; /* for ADSL connection */
};
/* these are to be used only by dhcp.c */
char * guess_netmask(char * ip_addr);
int configure_net_device(struct interface_info * intf);
extern char * hostname;
extern char * domain;
extern struct in_addr gateway;
extern struct in_addr dns_server;
extern struct in_addr dns_server2;
#endif

392
newt-frontend.c Normal file
View File

@ -0,0 +1,392 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
/*
* Each different frontend must implement all functions defined in frontend.h
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/time.h>
#include "newt/newt.h"
#include "frontend.h"
void init_frontend(char * welcome_msg)
{
int i;
for (i=0; i<38; i++) printf("\n");
newtInit();
newtCls();
newtDrawRootText(0, 0, welcome_msg);
newtPushHelpLine(" <Alt-F1> for here, <Alt-F3> to see the logs, <Alt-F4> for kernel msg");
newtRefresh();
}
void finish_frontend(void)
{
newtFinished();
}
void verror_message(char *msg, va_list ap)
{
newtWinMessagev("Error", "Ok", msg, ap);
}
void vinfo_message(char *msg, va_list ap)
{
newtWinMessagev("Notice", "Ok", msg, ap);
}
void vwait_message(char *msg, va_list ap)
{
int width, height;
char * title = "Please wait...";
newtComponent c, f;
newtGrid grid;
char * buf = NULL;
char * flowed;
int size = 0;
int i = 0;
do {
size += 1000;
if (buf) free(buf);
buf = malloc(size);
i = vsnprintf(buf, size, msg, ap);
} while (i >= size || i == -1);
flowed = newtReflowText(buf, 60, 5, 5, &width, &height);
c = newtTextbox(-1, -1, width, height, NEWT_TEXTBOX_WRAP);
newtTextboxSetText(c, flowed);
grid = newtCreateGrid(1, 1);
newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, c, 0, 0, 0, 0, 0, 0);
newtGridWrappedWindow(grid, title);
free(flowed);
free(buf);
f = newtForm(NULL, NULL, 0);
newtFormAddComponent(f, c);
newtDrawForm(f);
newtRefresh();
newtFormDestroy(f);
}
void remove_wait_message(void)
{
newtPopWindow();
}
static newtComponent form = NULL, scale = NULL;
static int size_progress;
static int actually_drawn;
static char * msg_progress;
void init_progression(char *msg, int size)
{
size_progress = size;
if (size) {
actually_drawn = 0;
newtCenteredWindow(70, 5, "Please wait...");
form = newtForm(NULL, NULL, 0);
newtFormAddComponent(form, newtLabel(1, 1, msg));
scale = newtScale(1, 3, 68, size);
newtFormAddComponent(form, scale);
newtDrawForm(form);
newtRefresh();
}
else {
wait_message(msg);
msg_progress = msg;
}
}
void update_progression(int current_size)
{
if (size_progress) {
if (current_size <= size_progress)
newtScaleSet(scale, current_size);
newtRefresh();
}
else {
struct timeval t;
int time;
static int last_time = -1;
gettimeofday(&t, NULL);
time = t.tv_sec*3 + t.tv_usec/300000;
if (time != last_time) {
char msg_prog_final[500];
sprintf(msg_prog_final, "%s (%d bytes read) ", msg_progress, current_size);
remove_wait_message();
wait_message(msg_prog_final);
}
last_time = time;
}
}
void end_progression(void)
{
if (size_progress) {
newtPopWindow();
newtFormDestroy(form);
}
else
remove_wait_message();
}
enum return_type ask_from_list_comments(char *msg, char ** elems, char ** elems_comments, char ** choice)
{
char * items[500];
int answer = 0, rc;
char ** sav_elems = elems;
int i;
i = 0;
while (elems && *elems) {
int j = (*elems_comments) ? strlen(*elems_comments) : 0;
items[i] = malloc(sizeof(char) * (strlen(*elems) + j + 4));
strcpy(items[i], *elems);
if (*elems_comments) {
strcat(items[i], " (");
strcat(items[i], *elems_comments);
strcat(items[i], ")");
}
elems_comments++;
i++;
elems++;
}
items[i] = NULL;
rc = newtWinMenu("Please choose...", msg, 52, 5, 5, 7, items, &answer, "Ok", "Cancel", NULL);
if (rc == 2)
return RETURN_BACK;
*choice = strdup(sav_elems[answer]);
return RETURN_OK;
}
enum return_type ask_from_list(char *msg, char ** elems, char ** choice)
{
int answer = 0, rc;
rc = newtWinMenu("Please choose...", msg, 52, 5, 5, 7, elems, &answer, "Ok", "Cancel", NULL);
if (rc == 2)
return RETURN_BACK;
*choice = strdup(elems[answer]);
return RETURN_OK;
}
enum return_type ask_yes_no(char *msg)
{
int rc;
rc = newtWinTernary("Please answer...", "Yes", "No", "Back", msg);
if (rc == 1)
return RETURN_OK;
else if (rc == 3)
return RETURN_BACK;
else return RETURN_ERROR;
}
static void (*callback_real_function)(char ** strings) = NULL;
static void default_callback(newtComponent co, void * data)
{
newtComponent * entries = data;
char * strings[50], ** ptr;
if (!callback_real_function)
return;
ptr = strings;
while (entries && *entries) {
*ptr = newtEntryGetValue(*entries);
entries++;
ptr++;
}
callback_real_function(strings);
ptr = strings;
entries = data;
while (entries && *entries) {
newtEntrySet(*entries, strdup(*ptr), 1);
entries++;
ptr++;
}
}
/* only supports up to 50 buttons and entries -- shucks! */
static int mynewtWinEntries(char * title, char * text, int suggestedWidth, int flexDown,
int flexUp, int dataWidth, void (*callback_func)(char ** strings),
struct newtWinEntry * items, char * button1, ...) {
newtComponent buttons[50], result, form, textw;
newtGrid grid, buttonBar, subgrid;
int numItems;
int rc, i;
int numButtons;
char * buttonName;
newtComponent entries[50];
va_list args;
textw = newtTextboxReflowed(-1, -1, text, suggestedWidth, flexDown,
flexUp, 0);
for (numItems = 0; items[numItems].text; numItems++);
buttonName = button1, numButtons = 0;
va_start(args, button1);
while (buttonName) {
buttons[numButtons] = newtButton(-1, -1, buttonName);
numButtons++;
buttonName = va_arg(args, char *);
}
va_end(args);
buttonBar = newtCreateGrid(numButtons, 1);
for (i = 0; i < numButtons; i++) {
newtGridSetField(buttonBar, i, 0, NEWT_GRID_COMPONENT,
buttons[i],
i ? 1 : 0, 0, 0, 0, 0, 0);
}
if (callback_func) {
callback_real_function = callback_func;
entries[numItems] = NULL;
}
else
callback_real_function = NULL;
subgrid = newtCreateGrid(2, numItems);
for (i = 0; i < numItems; i++) {
newtComponent entr = newtEntry(-1, -1, items[i].value ?
*items[i].value : NULL, dataWidth,
items[i].value, items[i].flags);
newtGridSetField(subgrid, 0, i, NEWT_GRID_COMPONENT,
newtLabel(-1, -1, items[i].text),
0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
newtGridSetField(subgrid, 1, i, NEWT_GRID_COMPONENT,
entr,
1, 0, 0, 0, 0, 0);
if (callback_func) {
entries[i] = entr;
newtComponentAddCallback(entr, default_callback, entries);
}
}
grid = newtCreateGrid(1, 3);
form = newtForm(NULL, 0, 0);
newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, textw,
0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, subgrid,
0, 1, 0, 0, 0, 0);
newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttonBar,
0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
newtGridAddComponentsToForm(grid, form, 1);
newtGridWrappedWindow(grid, title);
newtGridFree(grid, 1);
result = newtRunForm(form);
for (rc = 0; rc < numItems; rc++)
*items[rc].value = strdup(*items[rc].value);
for (rc = 0; result != buttons[rc] && rc < numButtons; rc++);
if (rc == numButtons)
rc = 0; /* F12 */
else
rc++;
newtFormDestroy(form);
newtPopWindow();
return rc;
}
enum return_type ask_from_entries(char *msg, char ** questions, char *** answers, int entry_size, void (*callback_func)(char ** strings))
{
struct newtWinEntry entries[50];
int j, i = 0;
int rc;
char ** already_answers = NULL;
while (questions && *questions) {
entries[i].text = *questions;
entries[i].flags = NEWT_FLAG_SCROLL | (!strcmp(*questions, "Password") ? NEWT_FLAG_PASSWORD : 0);
i++;
questions++;
}
entries[i].text = NULL;
entries[i].value = NULL;
if (*answers == NULL)
*answers = (char **) malloc(sizeof(char *) * i);
else
already_answers = *answers;
for (j = 0 ; j < i ; j++) {
entries[j].value = &((*answers)[j]);
if (already_answers && *already_answers) {
*(entries[j].value) = *already_answers;
already_answers++;
} else
*(entries[j].value) = NULL;
}
rc = mynewtWinEntries("Please fill entries...", msg, 52, 5, 5, entry_size, callback_func, entries, "Ok", "Cancel", NULL);
if (rc == 3)
return RETURN_BACK;
if (rc != 1)
return RETURN_ERROR;
return RETURN_OK;
}

54
nfs_mount4.h Normal file
View File

@ -0,0 +1,54 @@
/*
* We want to be able to compile mount on old kernels in such a way
* that the binary will work well on more recent kernels.
* Thus, if necessary we teach nfsmount.c the structure of new fields
* that will come later.
*
* Moreover, the new kernel includes conflict with glibc includes
* so it is easiest to ignore the kernel altogether (at compile time).
*/
#define NFS_MOUNT_VERSION 4
struct nfs2_fh {
char data[32];
};
struct nfs3_fh {
unsigned short size;
unsigned char data[64];
};
struct nfs_mount_data {
int version; /* 1 */
int fd; /* 1 */
struct nfs2_fh old_root; /* 1 */
int flags; /* 1 */
int rsize; /* 1 */
int wsize; /* 1 */
int timeo; /* 1 */
int retrans; /* 1 */
int acregmin; /* 1 */
int acregmax; /* 1 */
int acdirmin; /* 1 */
int acdirmax; /* 1 */
struct sockaddr_in addr; /* 1 */
char hostname[256]; /* 1 */
int namlen; /* 2 */
unsigned int bsize; /* 3 */
struct nfs3_fh root; /* 4 */
};
/* bits in the flags field */
#define NFS_MOUNT_SOFT 0x0001 /* 1 */
#define NFS_MOUNT_INTR 0x0002 /* 1 */
#define NFS_MOUNT_SECURE 0x0004 /* 1 */
#define NFS_MOUNT_POSIX 0x0008 /* 1 */
#define NFS_MOUNT_NOCTO 0x0010 /* 1 */
#define NFS_MOUNT_NOAC 0x0020 /* 1 */
#define NFS_MOUNT_TCP 0x0040 /* 2 */
#define NFS_MOUNT_VER3 0x0080 /* 3 */
#define NFS_MOUNT_KERBEROS 0x0100 /* 3 */
#define NFS_MOUNT_NONLM 0x0200 /* 3 */
#define NFS_MOUNT_BROKEN_SUID 0x0400 /* 4 */

739
nfsmount.c Normal file
View File

@ -0,0 +1,739 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2003 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
* basing on nfsmount.c from util-linux-2.11z:
* - use our logging facilities
* - use our host resolving stuff
* - remove unneeded code
*/
/*
* nfsmount.c -- Linux NFS mount
* Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
*
* 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.
*
* Wed Feb 8 12:51:48 1995, biro@yggdrasil.com (Ross Biro): allow all port
* numbers to be specified on the command line.
*
* Fri, 8 Mar 1996 18:01:39, Swen Thuemmler <swen@uni-paderborn.de>:
* Omit the call to connect() for Linux version 1.3.11 or later.
*
* Wed Oct 1 23:55:28 1997: Dick Streefland <dick_streefland@tasking.com>
* Implemented the "bg", "fg" and "retry" mount options for NFS.
*
* 1999-02-22 Arkadiusz Mikiewicz <misiek@pld.ORG.PL>
* - added Native Language Support
*
* Modified by Olaf Kirch and Trond Myklebust for new NFS code,
* plus NFSv3 stuff.
*
* 2003-04-14 David Black <david.black@xilinx.com>
* - added support for multiple hostname NFS mounts
*/
/*
* nfsmount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
*/
#define HAVE_rpcsvc_nfs_prot_h
#define HAVE_inet_aton
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <time.h>
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
//#include <sys/socket.h>
#include <sys/time.h>
#include <sys/utsname.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// #include <values.h>
#include "nfsmount.h"
#ifdef HAVE_rpcsvc_nfs_prot_h
#include <rpcsvc/nfs_prot.h>
#else
#include <linux/nfs.h>
#define nfsstat nfs_stat
#endif
#include "nfs_mount4.h"
#include "log.h"
#include "dns.h"
#ifndef NFS_PORT
#define NFS_PORT 2049
#endif
#ifndef NFS_FHSIZE
#define NFS_FHSIZE 32
#endif
static char *nfs_strerror(int stat);
#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
#define MAX_NFSPROT ((nfs_mount_version >= 4) ? 3 : 2)
bool_t
xdr_fhandle3 (XDR *xdrs, fhandle3 *objp)
{
if (!xdr_bytes (xdrs, (char **)&objp->fhandle3_val, (u_int *) &objp->fhandle3_len, FHSIZE3))
return FALSE;
return TRUE;
}
bool_t
xdr_mountstat3 (XDR *xdrs, mountstat3 *objp)
{
if (!xdr_enum (xdrs, (enum_t *) objp))
return FALSE;
return TRUE;
}
bool_t
xdr_mountres3_ok (XDR *xdrs, mountres3_ok *objp)
{
if (!xdr_fhandle3 (xdrs, &objp->fhandle))
return FALSE;
if (!xdr_array (xdrs, (char **)&objp->auth_flavours.auth_flavours_val, (u_int *) &objp->auth_flavours.auth_flavours_len, ~0,
sizeof (int), (xdrproc_t) xdr_int))
return FALSE;
return TRUE;
}
bool_t
xdr_mountres3 (XDR *xdrs, mountres3 *objp)
{
if (!xdr_mountstat3 (xdrs, &objp->fhs_status))
return FALSE;
switch (objp->fhs_status) {
case MNT_OK:
if (!xdr_mountres3_ok (xdrs, &objp->mountres3_u.mountinfo))
return FALSE;
break;
default:
break;
}
return TRUE;
}
bool_t
xdr_dirpath (XDR *xdrs, dirpath *objp)
{
if (!xdr_string (xdrs, objp, MNTPATHLEN))
return FALSE;
return TRUE;
}
bool_t
xdr_fhandle (XDR *xdrs, fhandle objp)
{
if (!xdr_opaque (xdrs, objp, FHSIZE))
return FALSE;
return TRUE;
}
bool_t
xdr_fhstatus (XDR *xdrs, fhstatus *objp)
{
if (!xdr_u_int (xdrs, &objp->fhs_status))
return FALSE;
switch (objp->fhs_status) {
case 0:
if (!xdr_fhandle (xdrs, objp->fhstatus_u.fhs_fhandle))
return FALSE;
break;
default:
break;
}
return TRUE;
}
static int
linux_version_code(void) {
struct utsname my_utsname;
int p, q, r;
if (uname(&my_utsname) == 0) {
p = atoi(strtok(my_utsname.release, "."));
q = atoi(strtok(NULL, "."));
r = atoi(strtok(NULL, "."));
return MAKE_VERSION(p,q,r);
}
return 0;
}
/*
* Unfortunately, the kernel prints annoying console messages
* in case of an unexpected nfs mount version (instead of
* just returning some error). Therefore we'll have to try
* and figure out what version the kernel expects.
*
* Variables:
* NFS_MOUNT_VERSION: these nfsmount sources at compile time
* nfs_mount_version: version this source and running kernel can handle
*/
static int
find_kernel_nfs_mount_version(void) {
static int kernel_version = -1;
int nfs_mount_version = NFS_MOUNT_VERSION;
if (kernel_version == -1)
kernel_version = linux_version_code();
if (kernel_version) {
if (kernel_version < MAKE_VERSION(2,1,32))
nfs_mount_version = 1;
else if (kernel_version < MAKE_VERSION(2,2,18))
nfs_mount_version = 3;
else if (kernel_version < MAKE_VERSION(2,3,0))
nfs_mount_version = 4; /* since 2.2.18pre9 */
else if (kernel_version < MAKE_VERSION(2,3,99))
nfs_mount_version = 3;
else
nfs_mount_version = 4; /* since 2.3.99pre4 */
}
if (nfs_mount_version > NFS_MOUNT_VERSION)
nfs_mount_version = NFS_MOUNT_VERSION;
log_message("nfsmount: kernel_nfs_mount_version: %d", nfs_mount_version);
return nfs_mount_version;
}
static struct pmap *
get_mountport(struct sockaddr_in *server_addr,
long unsigned prog,
long unsigned version,
long unsigned proto,
long unsigned port,
int nfs_mount_version)
{
struct pmaplist *pmap;
static struct pmap p = {0, 0, 0, 0};
if (version > MAX_NFSPROT)
version = MAX_NFSPROT;
if (!prog)
prog = MOUNTPROG;
p.pm_prog = prog;
p.pm_vers = version;
p.pm_prot = proto;
p.pm_port = port;
server_addr->sin_port = PMAPPORT;
pmap = pmap_getmaps(server_addr);
while (pmap) {
if (pmap->pml_map.pm_prog != prog)
goto next;
if (!version && p.pm_vers > pmap->pml_map.pm_vers)
goto next;
if (version > 2 && pmap->pml_map.pm_vers != version)
goto next;
if (version && version <= 2 && pmap->pml_map.pm_vers > 2)
goto next;
if (pmap->pml_map.pm_vers > MAX_NFSPROT ||
(proto && p.pm_prot && pmap->pml_map.pm_prot != proto) ||
(port && pmap->pml_map.pm_port != port))
goto next;
memcpy(&p, &pmap->pml_map, sizeof(p));
next:
pmap = pmap->pml_next;
}
if (!p.pm_vers)
p.pm_vers = MOUNTVERS;
if (!p.pm_prot)
p.pm_prot = IPPROTO_TCP;
return &p;
}
int nfsmount_prepare(const char *spec, char **mount_opts)
{
char hostdir[1024];
CLIENT *mclient;
char *hostname, *dirname, *mounthost = NULL;
struct timeval total_timeout;
enum clnt_stat clnt_stat;
static struct nfs_mount_data data;
int nfs_mount_version;
int val;
struct sockaddr_in server_addr;
struct sockaddr_in mount_server_addr;
struct pmap *pm_mnt;
int msock, fsock;
struct timeval retry_timeout;
union {
struct fhstatus nfsv2;
struct mountres3 nfsv3;
} status;
char *s;
int port, mountport, proto, soft, intr;
int posix, nocto, noac, broken_suid, nolock;
int retry, tcp;
int mountprog, mountvers, nfsprog, nfsvers;
int retval;
time_t t;
time_t prevt;
time_t timeout;
nfs_mount_version = find_kernel_nfs_mount_version();
retval = -1;
msock = fsock = -1;
mclient = NULL;
if (strlen(spec) >= sizeof(hostdir)) {
log_message("nfsmount: excessively long host:dir argument");
goto fail;
}
strcpy(hostdir, spec);
if ((s = strchr(hostdir, ':'))) {
hostname = hostdir;
dirname = s + 1;
*s = '\0';
} else {
log_message("nfsmount: directory to mount not in host:dir format");
goto fail;
}
server_addr.sin_family = AF_INET;
#ifdef HAVE_inet_aton
if (!inet_aton(hostname, &server_addr.sin_addr))
#endif
{
if (mygethostbyname(hostname, &server_addr.sin_addr)) {
log_message("nfsmount: can't get address for %s", hostname);
goto fail;
}
}
memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr));
/* Set default options.
* rsize/wsize (and bsize, for ver >= 3) are left 0 in order to
* let the kernel decide.
* timeo is filled in after we know whether it'll be TCP or UDP. */
memset(&data, 0, sizeof(data));
data.retrans = 3;
data.acregmin = 3;
data.acregmax = 60;
data.acdirmin = 30;
data.acdirmax = 60;
#if NFS_MOUNT_VERSION >= 2
data.namlen = NAME_MAX;
#endif
soft = 1;
intr = 0;
posix = 0;
nocto = 0;
nolock = 1;
broken_suid = 0;
noac = 0;
retry = 10000; /* 10000 minutes ~ 1 week */
tcp = 0;
mountprog = MOUNTPROG;
mountvers = 0;
port = 0;
mountport = 0;
nfsprog = NFS_PROGRAM;
nfsvers = 0;
retry_mount:
proto = (tcp) ? IPPROTO_TCP : IPPROTO_UDP;
data.flags = (soft ? NFS_MOUNT_SOFT : 0)
| (intr ? NFS_MOUNT_INTR : 0)
| (posix ? NFS_MOUNT_POSIX : 0)
| (nocto ? NFS_MOUNT_NOCTO : 0)
| (noac ? NFS_MOUNT_NOAC : 0);
#if NFS_MOUNT_VERSION >= 2
if (nfs_mount_version >= 2)
data.flags |= (tcp ? NFS_MOUNT_TCP : 0);
#endif
#if NFS_MOUNT_VERSION >= 3
if (nfs_mount_version >= 3)
data.flags |= (nolock ? NFS_MOUNT_NONLM : 0);
#endif
#if NFS_MOUNT_VERSION >= 4
if (nfs_mount_version >= 4)
data.flags |= (broken_suid ? NFS_MOUNT_BROKEN_SUID : 0);
#endif
if (nfsvers > MAX_NFSPROT) {
log_message("NFSv%d not supported!", nfsvers);
return 0;
}
if (mountvers > MAX_NFSPROT) {
log_message("NFSv%d not supported!", nfsvers);
return 0;
}
if (nfsvers && !mountvers)
mountvers = (nfsvers < 3) ? 1 : nfsvers;
if (nfsvers && nfsvers < mountvers)
mountvers = nfsvers;
/* Adjust options if none specified */
if (!data.timeo)
data.timeo = tcp ? 70 : 7;
#ifdef NFS_MOUNT_DEBUG
log_message("rsize = %d, wsize = %d, timeo = %d, retrans = %d",
data.rsize, data.wsize, data.timeo, data.retrans);
log_message("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)",
data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
log_message("port = %d, retry = %d, flags = %.8x",
port, retry, data.flags);
log_message("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d",
mountprog, mountvers, nfsprog, nfsvers);
log_message("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d",
(data.flags & NFS_MOUNT_SOFT) != 0,
(data.flags & NFS_MOUNT_INTR) != 0,
(data.flags & NFS_MOUNT_POSIX) != 0,
(data.flags & NFS_MOUNT_NOCTO) != 0,
(data.flags & NFS_MOUNT_NOAC) != 0);
#if NFS_MOUNT_VERSION >= 2
log_message("tcp = %d",
(data.flags & NFS_MOUNT_TCP) != 0);
#endif
#endif
data.version = nfs_mount_version;
*mount_opts = (char *) &data;
/* create mount deamon client */
/* See if the nfs host = mount host. */
if (mounthost) {
if (mounthost[0] >= '0' && mounthost[0] <= '9') {
mount_server_addr.sin_family = AF_INET;
mount_server_addr.sin_addr.s_addr = inet_addr(hostname);
} else {
if (mygethostbyname(mounthost, &mount_server_addr.sin_addr)) {
log_message("nfsmount: can't get address for %s", mounthost);
goto fail;
}
}
}
/*
* The following loop implements the mount retries. On the first
* call, "running_bg" is 0. When the mount times out, and the
* "bg" option is set, the exit status EX_BG will be returned.
* For a backgrounded mount, there will be a second call by the
* child process with "running_bg" set to 1.
*
* The case where the mount point is not present and the "bg"
* option is set, is treated as a timeout. This is done to
* support nested mounts.
*
* The "retry" count specified by the user is the number of
* minutes to retry before giving up.
*
* Only the first error message will be displayed.
*/
retry_timeout.tv_sec = 3;
retry_timeout.tv_usec = 0;
total_timeout.tv_sec = 20;
total_timeout.tv_usec = 0;
timeout = time(NULL) + 60 * retry;
prevt = 0;
t = 30;
val = 1;
/* be careful not to use too many CPU cycles */
if (t - prevt < 30)
sleep(30);
pm_mnt = get_mountport(&mount_server_addr,
mountprog,
mountvers,
proto,
mountport,
nfs_mount_version);
/* contact the mount daemon via TCP */
mount_server_addr.sin_port = htons(pm_mnt->pm_port);
msock = RPC_ANYSOCK;
switch (pm_mnt->pm_prot) {
case IPPROTO_UDP:
mclient = clntudp_create(&mount_server_addr,
pm_mnt->pm_prog,
pm_mnt->pm_vers,
retry_timeout,
&msock);
if (mclient)
break;
mount_server_addr.sin_port =
htons(pm_mnt->pm_port);
msock = RPC_ANYSOCK;
case IPPROTO_TCP:
mclient = clnttcp_create(&mount_server_addr,
pm_mnt->pm_prog,
pm_mnt->pm_vers,
&msock, 0, 0);
break;
default:
mclient = 0;
}
if (mclient) {
/* try to mount hostname:dirname */
mclient->cl_auth = authunix_create_default();
/* make pointers in xdr_mountres3 NULL so
* that xdr_array allocates memory for us
*/
memset(&status, 0, sizeof(status));
log_message("nfsmount: doing client call in nfs version: %ld", pm_mnt->pm_vers);
if (pm_mnt->pm_vers == 3)
clnt_stat = clnt_call(mclient,
MOUNTPROC3_MNT,
(xdrproc_t) xdr_dirpath,
(caddr_t) &dirname,
(xdrproc_t) xdr_mountres3,
(caddr_t) &status,
total_timeout);
else
clnt_stat = clnt_call(mclient,
MOUNTPROC_MNT,
(xdrproc_t) xdr_dirpath,
(caddr_t) &dirname,
(xdrproc_t) xdr_fhstatus,
(caddr_t) &status,
total_timeout);
if (clnt_stat == RPC_SUCCESS)
goto succeeded;
if (prevt == 0)
clnt_perror(mclient, "mount");
auth_destroy(mclient->cl_auth);
clnt_destroy(mclient);
mclient = 0;
close(msock);
} else {
if (prevt == 0)
clnt_pcreateerror("mount");
}
prevt = t;
goto fail;
succeeded:
nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers;
if (nfsvers == 2) {
if (status.nfsv2.fhs_status != 0) {
log_message("nfsmount: %s:%s failed, reason given by server: %s",
hostname, dirname, nfs_strerror(status.nfsv2.fhs_status));
goto fail;
}
memcpy(data.root.data,
(char *) status.nfsv2.fhstatus_u.fhs_fhandle,
NFS_FHSIZE);
#if NFS_MOUNT_VERSION >= 4
data.root.size = NFS_FHSIZE;
memcpy(data.old_root.data,
(char *) status.nfsv2.fhstatus_u.fhs_fhandle,
NFS_FHSIZE);
#endif
} else {
#if NFS_MOUNT_VERSION >= 4
fhandle3 *fhandle;
if (status.nfsv3.fhs_status != 0) {
log_message("nfsmount: %s:%s failed, reason given by server: %s",
hostname, dirname, nfs_strerror(status.nfsv3.fhs_status));
goto fail;
}
fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle;
memset(data.old_root.data, 0, NFS_FHSIZE);
memset(&data.root, 0, sizeof(data.root));
data.root.size = fhandle->fhandle3_len;
memcpy(data.root.data,
(char *) fhandle->fhandle3_val,
fhandle->fhandle3_len);
data.flags |= NFS_MOUNT_VER3;
#endif
}
/* create nfs socket for kernel */
if (tcp) {
if (nfs_mount_version < 3) {
log_message("NFS over TCP is not supported.");
goto fail;
}
fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
} else
fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (fsock < 0) {
log_perror("nfs socket");
goto fail;
}
if (bindresvport(fsock, 0) < 0) {
log_perror("nfs bindresvport");
goto fail;
}
if (port == 0) {
server_addr.sin_port = PMAPPORT;
port = pmap_getport(&server_addr, nfsprog, nfsvers,
tcp ? IPPROTO_TCP : IPPROTO_UDP);
#if 1
/* Here we check to see if user is mounting with the
* tcp option. If so, and if the portmap returns a
* '0' for port (service unavailable), we then notify
* the user, and retry with udp.
*/
if (port == 0 && tcp == 1) {
log_message("NFS server reported TCP not available, retrying with UDP...");
tcp = 0;
goto retry_mount;
}
#endif
if (port == 0)
port = NFS_PORT;
#ifdef NFS_MOUNT_DEBUG
else
log_message("used portmapper to find NFS port");
#endif
}
#ifdef NFS_MOUNT_DEBUG
log_message("using port %d for nfs deamon", port);
#endif
server_addr.sin_port = htons(port);
/*
* connect() the socket for kernels 1.3.10 and below only,
* to avoid problems with multihomed hosts.
* --Swen
*/
if (linux_version_code() <= 66314
&& connect(fsock, (struct sockaddr *) &server_addr,
sizeof (server_addr)) < 0) {
log_perror("nfs connect");
goto fail;
}
/* prepare data structure for kernel */
data.fd = fsock;
memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr));
strncpy(data.hostname, hostname, sizeof(data.hostname));
/* clean up */
auth_destroy(mclient->cl_auth);
clnt_destroy(mclient);
close(msock);
return 0;
/* abort */
fail:
if (msock != -1) {
if (mclient) {
auth_destroy(mclient->cl_auth);
clnt_destroy(mclient);
}
close(msock);
}
if (fsock != -1)
close(fsock);
return retval;
}
/*
* We need to translate between nfs status return values and
* the local errno values which may not be the same.
*
* Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>: change errno:
* "after #include <errno.h> the symbol errno is reserved for any use,
* it cannot even be used as a struct tag or field name".
*/
#ifndef EDQUOT
#define EDQUOT ENOSPC
#endif
static struct {
enum nfsstat stat;
int errnum;
} nfs_errtbl[] = {
{ NFS_OK, 0 },
{ NFSERR_PERM, EPERM },
{ NFSERR_NOENT, ENOENT },
{ NFSERR_IO, EIO },
{ NFSERR_NXIO, ENXIO },
{ NFSERR_ACCES, EACCES },
{ NFSERR_EXIST, EEXIST },
{ NFSERR_NODEV, ENODEV },
{ NFSERR_NOTDIR, ENOTDIR },
{ NFSERR_ISDIR, EISDIR },
#ifdef NFSERR_INVAL
{ NFSERR_INVAL, EINVAL }, /* that Sun forgot */
#endif
{ NFSERR_FBIG, EFBIG },
{ NFSERR_NOSPC, ENOSPC },
{ NFSERR_ROFS, EROFS },
{ NFSERR_NAMETOOLONG, ENAMETOOLONG },
{ NFSERR_NOTEMPTY, ENOTEMPTY },
{ NFSERR_DQUOT, EDQUOT },
{ NFSERR_STALE, ESTALE },
#ifdef EWFLUSH
{ NFSERR_WFLUSH, EWFLUSH },
#endif
/* Throw in some NFSv3 values for even more fun (HP returns these) */
{ 71, EREMOTE },
{ -1, EIO }
};
static char *nfs_strerror(int stat)
{
int i;
static char buf[256];
for (i = 0; nfs_errtbl[i].stat != (unsigned)-1; i++) {
if (nfs_errtbl[i].stat == (unsigned)stat)
return strerror(nfs_errtbl[i].errnum);
}
sprintf(buf, "unknown nfs status return value: %d", stat);
return buf;
}

331
nfsmount.h Normal file
View File

@ -0,0 +1,331 @@
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#ifndef _NFSMOUNT_H_RPCGEN
#define _NFSMOUNT_H_RPCGEN
#include <rpc/rpc.h>
int nfsmount_prepare(const char *spec, char **mount_opts);
#ifdef __cplusplus
extern "C" {
#endif
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user or with the express written consent of
* Sun Microsystems, Inc.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*/
/*
* Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
*/
/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
#ifndef _rpcsvc_mount_h
#define _rpcsvc_mount_h
#include <asm/types.h>
#define MNTPATHLEN 1024
#define MNTNAMLEN 255
#define FHSIZE 32
#define FHSIZE3 64
typedef char fhandle[FHSIZE];
typedef struct {
u_int fhandle3_len;
char *fhandle3_val;
} fhandle3;
enum mountstat3 {
MNT_OK = 0,
MNT3ERR_PERM = 1,
MNT3ERR_NOENT = 2,
MNT3ERR_IO = 5,
MNT3ERR_ACCES = 13,
MNT3ERR_NOTDIR = 20,
MNT3ERR_INVAL = 22,
MNT3ERR_NAMETOOLONG = 63,
MNT3ERR_NOTSUPP = 10004,
MNT3ERR_SERVERFAULT = 10006,
};
typedef enum mountstat3 mountstat3;
struct fhstatus {
u_int fhs_status;
union {
fhandle fhs_fhandle;
} fhstatus_u;
};
typedef struct fhstatus fhstatus;
struct mountres3_ok {
fhandle3 fhandle;
struct {
u_int auth_flavours_len;
int *auth_flavours_val;
} auth_flavours;
};
typedef struct mountres3_ok mountres3_ok;
struct mountres3 {
mountstat3 fhs_status;
union {
mountres3_ok mountinfo;
} mountres3_u;
};
typedef struct mountres3 mountres3;
typedef char *dirpath;
typedef char *name;
typedef struct mountbody *mountlist;
struct mountbody {
name ml_hostname;
dirpath ml_directory;
mountlist ml_next;
};
typedef struct mountbody mountbody;
typedef struct groupnode *groups;
struct groupnode {
name gr_name;
groups gr_next;
};
typedef struct groupnode groupnode;
typedef struct exportnode *exports;
struct exportnode {
dirpath ex_dir;
groups ex_groups;
exports ex_next;
};
typedef struct exportnode exportnode;
struct ppathcnf {
int pc_link_max;
short pc_max_canon;
short pc_max_input;
short pc_name_max;
short pc_path_max;
short pc_pipe_buf;
u_char pc_vdisable;
char pc_xxx;
short pc_mask[2];
};
typedef struct ppathcnf ppathcnf;
#endif /*!_rpcsvc_mount_h*/
#define MOUNTPROG 100005
#define MOUNTVERS 1
#if defined(__STDC__) || defined(__cplusplus)
#define MOUNTPROC_NULL 0
extern void * mountproc_null_1(void *, CLIENT *);
extern void * mountproc_null_1_svc(void *, struct svc_req *);
#define MOUNTPROC_MNT 1
extern fhstatus * mountproc_mnt_1(dirpath *, CLIENT *);
extern fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *);
#define MOUNTPROC_DUMP 2
extern mountlist * mountproc_dump_1(void *, CLIENT *);
extern mountlist * mountproc_dump_1_svc(void *, struct svc_req *);
#define MOUNTPROC_UMNT 3
extern void * mountproc_umnt_1(dirpath *, CLIENT *);
extern void * mountproc_umnt_1_svc(dirpath *, struct svc_req *);
#define MOUNTPROC_UMNTALL 4
extern void * mountproc_umntall_1(void *, CLIENT *);
extern void * mountproc_umntall_1_svc(void *, struct svc_req *);
#define MOUNTPROC_EXPORT 5
extern exports * mountproc_export_1(void *, CLIENT *);
extern exports * mountproc_export_1_svc(void *, struct svc_req *);
#define MOUNTPROC_EXPORTALL 6
extern exports * mountproc_exportall_1(void *, CLIENT *);
extern exports * mountproc_exportall_1_svc(void *, struct svc_req *);
extern int mountprog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
#else /* K&R C */
#define MOUNTPROC_NULL 0
extern void * mountproc_null_1();
extern void * mountproc_null_1_svc();
#define MOUNTPROC_MNT 1
extern fhstatus * mountproc_mnt_1();
extern fhstatus * mountproc_mnt_1_svc();
#define MOUNTPROC_DUMP 2
extern mountlist * mountproc_dump_1();
extern mountlist * mountproc_dump_1_svc();
#define MOUNTPROC_UMNT 3
extern void * mountproc_umnt_1();
extern void * mountproc_umnt_1_svc();
#define MOUNTPROC_UMNTALL 4
extern void * mountproc_umntall_1();
extern void * mountproc_umntall_1_svc();
#define MOUNTPROC_EXPORT 5
extern exports * mountproc_export_1();
extern exports * mountproc_export_1_svc();
#define MOUNTPROC_EXPORTALL 6
extern exports * mountproc_exportall_1();
extern exports * mountproc_exportall_1_svc();
extern int mountprog_1_freeresult ();
#endif /* K&R C */
#define MOUNTVERS_POSIX 2
#if defined(__STDC__) || defined(__cplusplus)
extern void * mountproc_null_2(void *, CLIENT *);
extern void * mountproc_null_2_svc(void *, struct svc_req *);
extern fhstatus * mountproc_mnt_2(dirpath *, CLIENT *);
extern fhstatus * mountproc_mnt_2_svc(dirpath *, struct svc_req *);
extern mountlist * mountproc_dump_2(void *, CLIENT *);
extern mountlist * mountproc_dump_2_svc(void *, struct svc_req *);
extern void * mountproc_umnt_2(dirpath *, CLIENT *);
extern void * mountproc_umnt_2_svc(dirpath *, struct svc_req *);
extern void * mountproc_umntall_2(void *, CLIENT *);
extern void * mountproc_umntall_2_svc(void *, struct svc_req *);
extern exports * mountproc_export_2(void *, CLIENT *);
extern exports * mountproc_export_2_svc(void *, struct svc_req *);
extern exports * mountproc_exportall_2(void *, CLIENT *);
extern exports * mountproc_exportall_2_svc(void *, struct svc_req *);
#define MOUNTPROC_PATHCONF 7
extern ppathcnf * mountproc_pathconf_2(dirpath *, CLIENT *);
extern ppathcnf * mountproc_pathconf_2_svc(dirpath *, struct svc_req *);
extern int mountprog_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
#else /* K&R C */
extern void * mountproc_null_2();
extern void * mountproc_null_2_svc();
extern fhstatus * mountproc_mnt_2();
extern fhstatus * mountproc_mnt_2_svc();
extern mountlist * mountproc_dump_2();
extern mountlist * mountproc_dump_2_svc();
extern void * mountproc_umnt_2();
extern void * mountproc_umnt_2_svc();
extern void * mountproc_umntall_2();
extern void * mountproc_umntall_2_svc();
extern exports * mountproc_export_2();
extern exports * mountproc_export_2_svc();
extern exports * mountproc_exportall_2();
extern exports * mountproc_exportall_2_svc();
#define MOUNTPROC_PATHCONF 7
extern ppathcnf * mountproc_pathconf_2();
extern ppathcnf * mountproc_pathconf_2_svc();
extern int mountprog_2_freeresult ();
#endif /* K&R C */
#define MOUNT_V3 3
#if defined(__STDC__) || defined(__cplusplus)
#define MOUNTPROC3_NULL 0
extern void * mountproc3_null_3(void *, CLIENT *);
extern void * mountproc3_null_3_svc(void *, struct svc_req *);
#define MOUNTPROC3_MNT 1
extern mountres3 * mountproc3_mnt_3(dirpath *, CLIENT *);
extern mountres3 * mountproc3_mnt_3_svc(dirpath *, struct svc_req *);
#define MOUNTPROC3_DUMP 2
extern mountlist * mountproc3_dump_3(void *, CLIENT *);
extern mountlist * mountproc3_dump_3_svc(void *, struct svc_req *);
#define MOUNTPROC3_UMNT 3
extern void * mountproc3_umnt_3(dirpath *, CLIENT *);
extern void * mountproc3_umnt_3_svc(dirpath *, struct svc_req *);
#define MOUNTPROC3_UMNTALL 4
extern void * mountproc3_umntall_3(void *, CLIENT *);
extern void * mountproc3_umntall_3_svc(void *, struct svc_req *);
#define MOUNTPROC3_EXPORT 5
extern exports * mountproc3_export_3(void *, CLIENT *);
extern exports * mountproc3_export_3_svc(void *, struct svc_req *);
extern int mountprog_3_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
#else /* K&R C */
#define MOUNTPROC3_NULL 0
extern void * mountproc3_null_3();
extern void * mountproc3_null_3_svc();
#define MOUNTPROC3_MNT 1
extern mountres3 * mountproc3_mnt_3();
extern mountres3 * mountproc3_mnt_3_svc();
#define MOUNTPROC3_DUMP 2
extern mountlist * mountproc3_dump_3();
extern mountlist * mountproc3_dump_3_svc();
#define MOUNTPROC3_UMNT 3
extern void * mountproc3_umnt_3();
extern void * mountproc3_umnt_3_svc();
#define MOUNTPROC3_UMNTALL 4
extern void * mountproc3_umntall_3();
extern void * mountproc3_umntall_3_svc();
#define MOUNTPROC3_EXPORT 5
extern exports * mountproc3_export_3();
extern exports * mountproc3_export_3_svc();
extern int mountprog_3_freeresult ();
#endif /* K&R C */
/* the xdr functions */
#if defined(__STDC__) || defined(__cplusplus)
extern bool_t xdr_fhandle (XDR *, fhandle);
extern bool_t xdr_fhandle3 (XDR *, fhandle3*);
extern bool_t xdr_mountstat3 (XDR *, mountstat3*);
extern bool_t xdr_fhstatus (XDR *, fhstatus*);
extern bool_t xdr_mountres3_ok (XDR *, mountres3_ok*);
extern bool_t xdr_mountres3 (XDR *, mountres3*);
extern bool_t xdr_dirpath (XDR *, dirpath*);
extern bool_t xdr_name (XDR *, name*);
extern bool_t xdr_mountlist (XDR *, mountlist*);
extern bool_t xdr_mountbody (XDR *, mountbody*);
extern bool_t xdr_groups (XDR *, groups*);
extern bool_t xdr_groupnode (XDR *, groupnode*);
extern bool_t xdr_exports (XDR *, exports*);
extern bool_t xdr_exportnode (XDR *, exportnode*);
extern bool_t xdr_ppathcnf (XDR *, ppathcnf*);
#else /* K&R C */
extern bool_t xdr_fhandle ();
extern bool_t xdr_fhandle3 ();
extern bool_t xdr_mountstat3 ();
extern bool_t xdr_fhstatus ();
extern bool_t xdr_mountres3_ok ();
extern bool_t xdr_mountres3 ();
extern bool_t xdr_dirpath ();
extern bool_t xdr_name ();
extern bool_t xdr_mountlist ();
extern bool_t xdr_mountbody ();
extern bool_t xdr_groups ();
extern bool_t xdr_groupnode ();
extern bool_t xdr_exports ();
extern bool_t xdr_exportnode ();
extern bool_t xdr_ppathcnf ();
#endif /* K&R C */
#ifdef __cplusplus
}
#endif
#endif /* !_NFSMOUNT_H_RPCGEN */

1
pci-resource/.cvsignore Normal file
View File

@ -0,0 +1 @@
pci-ids.h

25
pci-resource/Makefile Normal file
View File

@ -0,0 +1,25 @@
#******************************************************************************
#
# $Id$
#
# Guillaume Cottenceau (gc@mandrakesoft.com)
#
# Copyright 2000 MandrakeSoft
#
# This software may be freely redistributed under the terms of the GNU
# 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.
#
#*****************************************************************************
all: pci-ids.h
pci-ids.h: /usr/share/ldetect-lst/pcitable update-pci-ids.pl
perl update-pci-ids.pl > $@ || rm -f $@
clean:
rm -f pci-ids.h

74
pci-resource/update-pci-ids.pl Executable file
View File

@ -0,0 +1,74 @@
#!/usr/bin/perl
use MDK::Common;
-x "../mar/mar" or die "\t*FAILED* Sorry, need ../mar/mar binary\n";
require '/usr/bin/merge2pcitable.pl';
my $drivers = read_pcitable("/usr/share/ldetect-lst/pcitable");
print '
#define PCI_REVISION_ID 0x08 /* Revision ID */
struct pci_module_map {
unsigned short vendor; /* PCI vendor id */
unsigned short device; /* PCI device id */
const char *name; /* PCI human readable name */
const char *module; /* module to load */
};
';
my %t = ( network => [ 'network' ],
medias => [ 'hd', 'cdrom', 'other' ]
);
my %sanity_check =
arch() =~ /ia64/ ?
( network => [ '3c59x', 'eepro100', 'e100', 'tulip', 'via-rhine', 'ne2k-pci', '8139too', '3c90x' ],
medias => [ 'aic7xxx', 'advansys', 'sym53c8xx', 'initio' ],
) :
arch() =~ /ppc/ ?
( network => [ '3c59x', 'eepro100', 'tulip', 'via-rhine', 'ne2k-pci', '8139too' ],
medias => [ 'aic7xxx', 'sym53c8xx', 'initio' ],
) :
# ( network => [ '3c59x', 'eepro100', 'e100', 'tulip', 'via-rhine', 'ne2k-pci', '8139too', 'tlan', '3c90x' ],
( network => [ '3c59x', 'eepro100', 'e100', 'tulip', 'via-rhine', 'ne2k-pci', '8139too', 'tlan', 'b44', 'e1000', 'sk98lin', 'nvnet' ],
medias => [ 'aic7xxx', 'advansys', 'ncr53c8xx', 'sym53c8xx', 'initio', 'aic79xx' ],
);
foreach $type (keys %t) {
print STDERR "$type (checks: ", join('/', @{$sanity_check{$type}}), ") ";
my @modulez;
foreach $floppy (@{$t{$type}}) {
foreach $marfile (glob("../../all.modules/*/${floppy}_modules.mar")) {
-f $marfile or die "\t*FAILED* Sorry, need $marfile mar file\n";
my @modz = `../mar/mar -l $marfile`;
if ($marfile !~ /(2\.2\.14|19)|(other)/) {
foreach $mandatory (@{$sanity_check{$type}}) {
grep(/\t$mandatory\.o/, @modz) or die "\t*FAILED* Sanity check should prove that $mandatory.o be part of $marfile\n"
}
}
push @modulez, @modz;
print STDERR ".";
}
}
print "#ifndef DISABLE_".uc($type)."
struct pci_module_map ${type}_pci_ids[] = {
";
while (my ($k, $v) = each %$drivers) {
grep(/^\t$v->[0]\.o/, @modulez) or next;
$k =~ /^(....)(....)/;
printf qq|\t{ 0x%s, 0x%s, "%s", "%s" },\n|,
$1, $2, $v->[1], $v->[0];
}
print "};
int ${type}_num_ids = sizeof(${type}_pci_ids) / sizeof(struct pci_module_map);
#endif
";
print STDERR "\n";
}

48
pcmcia/Makefile Normal file
View File

@ -0,0 +1,48 @@
#******************************************************************************
#
# Guillaume Cottenceau (gc@mandrakesoft.com)
#
# Copyright 2000 MandrakeSoft
#
# This software may be freely redistributed under the terms of the GNU
# 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.
#
#*****************************************************************************
top_dir = ..
include $(top_dir)/Makefile.common
all: libpcmcia.a libpcmcia-DIET.a
clean:
rm -f *.o libpcmcia.a
FLAGS = -Wall -Os -fomit-frame-pointer -pipe -c -I.. -D_BSD_SOURCE
OBJS = pcmcia_probe.o cardmgr.o lex_config.o yacc_config.o
OBJS-DIET = $(subst .o,-DIET.o,$(OBJS))
libpcmcia.a: $(OBJS)
ar -cru $@ $^
ranlib $@
libpcmcia-DIET.a: $(OBJS-DIET)
ar -cru $@ $^
ranlib $@
$(OBJS): %.o: %.c
gcc $(FLAGS) $(GLIBC_INCLUDES) -c $< -o $@
$(OBJS-DIET): %-DIET.o: %.c
gcc $(FLAGS) $(DIETLIBC_INCLUDES) -c $< -o $@

195
pcmcia/bulkmem.h Normal file
View File

@ -0,0 +1,195 @@
/*
* Definitions for bulk memory services
*
* bulkmem.h 1.13 2001/08/24 12:16:12
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
* bulkmem.h 1.3 1995/05/27 04:49:49
*/
#ifndef _LINUX_BULKMEM_H
#define _LINUX_BULKMEM_H
/* For GetFirstRegion and GetNextRegion */
typedef struct region_info_t {
u_int Attributes;
u_int CardOffset;
u_int RegionSize;
u_int AccessSpeed;
u_int BlockSize;
u_int PartMultiple;
u_char JedecMfr, JedecInfo;
memory_handle_t next;
} region_info_t;
#define REGION_TYPE 0x0001
#define REGION_TYPE_CM 0x0000
#define REGION_TYPE_AM 0x0001
#define REGION_PREFETCH 0x0008
#define REGION_CACHEABLE 0x0010
#define REGION_BAR_MASK 0xe000
#define REGION_BAR_SHIFT 13
/* For OpenMemory */
typedef struct open_mem_t {
u_int Attributes;
u_int Offset;
} open_mem_t;
/* Attributes for OpenMemory */
#define MEMORY_TYPE 0x0001
#define MEMORY_TYPE_CM 0x0000
#define MEMORY_TYPE_AM 0x0001
#define MEMORY_EXCLUSIVE 0x0002
#define MEMORY_PREFETCH 0x0008
#define MEMORY_CACHEABLE 0x0010
#define MEMORY_BAR_MASK 0xe000
#define MEMORY_BAR_SHIFT 13
typedef struct eraseq_entry_t {
memory_handle_t Handle;
u_char State;
u_int Size;
u_int Offset;
void *Optional;
} eraseq_entry_t;
typedef struct eraseq_hdr_t {
int QueueEntryCnt;
eraseq_entry_t *QueueEntryArray;
} eraseq_hdr_t;
#define ERASE_QUEUED 0x00
#define ERASE_IN_PROGRESS(n) (((n) > 0) && ((n) < 0x80))
#define ERASE_IDLE 0xff
#define ERASE_PASSED 0xe0
#define ERASE_FAILED 0xe1
#define ERASE_MISSING 0x80
#define ERASE_MEDIA_WRPROT 0x84
#define ERASE_NOT_ERASABLE 0x85
#define ERASE_BAD_OFFSET 0xc1
#define ERASE_BAD_TECH 0xc2
#define ERASE_BAD_SOCKET 0xc3
#define ERASE_BAD_VCC 0xc4
#define ERASE_BAD_VPP 0xc5
#define ERASE_BAD_SIZE 0xc6
/* For CopyMemory */
typedef struct copy_op_t {
u_int Attributes;
u_int SourceOffset;
u_int DestOffset;
u_int Count;
} copy_op_t;
/* For ReadMemory and WriteMemory */
typedef struct mem_op_t {
u_int Attributes;
u_int Offset;
u_int Count;
} mem_op_t;
#define MEM_OP_BUFFER 0x01
#define MEM_OP_BUFFER_USER 0x00
#define MEM_OP_BUFFER_KERNEL 0x01
#define MEM_OP_DISABLE_ERASE 0x02
#define MEM_OP_VERIFY 0x04
/* For RegisterMTD */
typedef struct mtd_reg_t {
u_int Attributes;
u_int Offset;
u_long MediaID;
} mtd_reg_t;
/*
* Definitions for MTD requests
*/
typedef struct mtd_request_t {
u_int SrcCardOffset;
u_int DestCardOffset;
u_int TransferLength;
u_int Function;
u_long MediaID;
u_int Status;
u_int Timeout;
} mtd_request_t;
/* Fields in MTD Function */
#define MTD_REQ_ACTION 0x003
#define MTD_REQ_ERASE 0x000
#define MTD_REQ_READ 0x001
#define MTD_REQ_WRITE 0x002
#define MTD_REQ_COPY 0x003
#define MTD_REQ_NOERASE 0x004
#define MTD_REQ_VERIFY 0x008
#define MTD_REQ_READY 0x010
#define MTD_REQ_TIMEOUT 0x020
#define MTD_REQ_LAST 0x040
#define MTD_REQ_FIRST 0x080
#define MTD_REQ_KERNEL 0x100
/* Status codes */
#define MTD_WAITREQ 0x00
#define MTD_WAITTIMER 0x01
#define MTD_WAITRDY 0x02
#define MTD_WAITPOWER 0x03
/*
* Definitions for MTD helper functions
*/
/* For MTDModifyWindow */
typedef struct mtd_mod_win_t {
u_int Attributes;
u_int AccessSpeed;
u_int CardOffset;
} mtd_mod_win_t;
/* For MTDSetVpp */
typedef struct mtd_vpp_req_t {
u_char Vpp1, Vpp2;
} mtd_vpp_req_t;
/* For MTDRDYMask */
typedef struct mtd_rdy_req_t {
u_int Mask;
} mtd_rdy_req_t;
enum mtd_helper {
MTDRequestWindow, MTDModifyWindow, MTDReleaseWindow,
MTDSetVpp, MTDRDYMask
};
#ifdef IN_CARD_SERVICES
extern int MTDHelperEntry(int func, void *a1, void *a2);
#else
extern int MTDHelperEntry(int func, ...);
#endif
#endif /* _LINUX_BULKMEM_H */

157
pcmcia/bus_ops.h Normal file
View File

@ -0,0 +1,157 @@
/*
* bus_ops.h 1.12 2001/08/24 12:16:12
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#ifndef _LINUX_BUS_OPS_H
#define _LINUX_BUS_OPS_H
#include <linux/config.h>
#ifdef CONFIG_VIRTUAL_BUS
typedef struct bus_operations {
void *priv;
u32 (*b_in)(void *bus, u32 port, s32 sz);
void (*b_ins)(void *bus, u32 port, void *buf,
u32 count, s32 sz);
void (*b_out)(void *bus, u32 val, u32 port, s32 sz);
void (*b_outs)(void *bus, u32 port, void *buf,
u32 count, s32 sz);
void *(*b_ioremap)(void *bus, u_long ofs, u_long sz);
void (*b_iounmap)(void *bus, void *addr);
u32 (*b_read)(void *bus, void *addr, s32 sz);
void (*b_write)(void *bus, u32 val, void *addr, s32 sz);
void (*b_copy_from)(void *bus, void *d, void *s, u32 count);
void (*b_copy_to)(void *bus, void *d, void *s, u32 count);
int (*b_request_irq)(void *bus, u_int irq,
void (*handler)(int, void *,
struct pt_regs *),
u_long flags, const char *device,
void *dev_id);
void (*b_free_irq)(void *bus, u_int irq, void *dev_id);
} bus_operations;
#define bus_inb(b,p) (b)->b_in((b),(p),0)
#define bus_inw(b,p) (b)->b_in((b),(p),1)
#define bus_inl(b,p) (b)->b_in((b),(p),2)
#define bus_inw_ns(b,p) (b)->b_in((b),(p),-1)
#define bus_inl_ns(b,p) (b)->b_in((b),(p),-2)
#define bus_insb(b,p,a,c) (b)->b_ins((b),(p),(a),(c),0)
#define bus_insw(b,p,a,c) (b)->b_ins((b),(p),(a),(c),1)
#define bus_insl(b,p,a,c) (b)->b_ins((b),(p),(a),(c),2)
#define bus_insw_ns(b,p,a,c) (b)->b_ins((b),(p),(a),(c),-1)
#define bus_insl_ns(b,p,a,c) (b)->b_ins((b),(p),(a),(c),-2)
#define bus_outb(b,v,p) (b)->b_out((b),(v),(p),0)
#define bus_outw(b,v,p) (b)->b_out((b),(v),(p),1)
#define bus_outl(b,v,p) (b)->b_out((b),(v),(p),2)
#define bus_outw_ns(b,v,p) (b)->b_out((b),(v),(p),-1)
#define bus_outl_ns(b,v,p) (b)->b_out((b),(v),(p),-2)
#define bus_outsb(b,p,a,c) (b)->b_outs((b),(p),(a),(c),0)
#define bus_outsw(b,p,a,c) (b)->b_outs((b),(p),(a),(c),1)
#define bus_outsl(b,p,a,c) (b)->b_outs((b),(p),(a),(c),2)
#define bus_outsw_ns(b,p,a,c) (b)->b_outs((b),(p),(a),(c),-1)
#define bus_outsl_ns(b,p,a,c) (b)->b_outs((b),(p),(a),(c),-2)
#define bus_readb(b,a) (b)->b_read((b),(a),0)
#define bus_readw(b,a) (b)->b_read((b),(a),1)
#define bus_readl(b,a) (b)->b_read((b),(a),2)
#define bus_readw_ns(b,a) (b)->b_read((b),(a),-1)
#define bus_readl_ns(b,a) (b)->b_read((b),(a),-2)
#define bus_writeb(b,v,a) (b)->b_write((b),(v),(a),0)
#define bus_writew(b,v,a) (b)->b_write((b),(v),(a),1)
#define bus_writel(b,v,a) (b)->b_write((b),(v),(a),2)
#define bus_writew_ns(b,v,a) (b)->b_write((b),(v),(a),-1)
#define bus_writel_ns(b,v,a) (b)->b_write((b),(v),(a),-2)
#define bus_ioremap(b,s,n) (b)->b_ioremap((b),(s),(n))
#define bus_iounmap(b,a) (b)->b_iounmap((b),(a))
#define bus_memcpy_fromio(b,d,s,n) (b)->b_copy_from((b),(d),(s),(n))
#define bus_memcpy_toio(b,d,s,n) (b)->b_copy_to((b),(d),(s),(n))
#define bus_request_irq(b,i,h,f,n,d) \
(b)->b_request_irq((b),(i),(h),(f),(n),(d))
#define bus_free_irq(b,i,d) (b)->b_free_irq((b),(i),(d))
#else
#define bus_inb(b,p) inb(p)
#define bus_inw(b,p) inw(p)
#define bus_inl(b,p) inl(p)
#define bus_inw_ns(b,p) inw_ns(p)
#define bus_inl_ns(b,p) inl_ns(p)
#define bus_insb(b,p,a,c) insb(p,a,c)
#define bus_insw(b,p,a,c) insw(p,a,c)
#define bus_insl(b,p,a,c) insl(p,a,c)
#define bus_insw_ns(b,p,a,c) insw_ns(p,a,c)
#define bus_insl_ns(b,p,a,c) insl_ns(p,a,c)
#define bus_outb(b,v,p) outb(b,v,p)
#define bus_outw(b,v,p) outw(b,v,p)
#define bus_outl(b,v,p) outl(b,v,p)
#define bus_outw_ns(b,v,p) outw_ns(b,v,p)
#define bus_outl_ns(b,v,p) outl_ns(b,v,p)
#define bus_outsb(b,p,a,c) outsb(p,a,c)
#define bus_outsw(b,p,a,c) outsw(p,a,c)
#define bus_outsl(b,p,a,c) outsl(p,a,c)
#define bus_outsw_ns(b,p,a,c) outsw_ns(p,a,c)
#define bus_outsl_ns(b,p,a,c) outsl_ns(p,a,c)
#define bus_readb(b,a) readb(a)
#define bus_readw(b,a) readw(a)
#define bus_readl(b,a) readl(a)
#define bus_readw_ns(b,a) readw_ns(a)
#define bus_readl_ns(b,a) readl_ns(a)
#define bus_writeb(b,v,a) writeb(v,a)
#define bus_writew(b,v,a) writew(v,a)
#define bus_writel(b,v,a) writel(v,a)
#define bus_writew_ns(b,v,a) writew_ns(v,a)
#define bus_writel_ns(b,v,a) writel_ns(v,a)
#define bus_ioremap(b,s,n) ioremap(s,n)
#define bus_iounmap(b,a) iounmap(a)
#define bus_memcpy_fromio(b,d,s,n) memcpy_fromio(d,s,n)
#define bus_memcpy_toio(b,d,s,n) memcpy_toio(d,s,n)
#ifdef CONFIG_8xx
#define bus_request_irq(b,i,h,f,n,d) request_8xxirq((i),(h),(f),(n),(d))
#else
#define bus_request_irq(b,i,h,f,n,d) request_irq((i),(h),(f),(n),(d))
#endif
#define bus_free_irq(b,i,d) free_irq((i),(d))
#endif /* CONFIG_VIRTUAL_BUS */
#endif /* _LINUX_BUS_OPS_H */

1471
pcmcia/cardmgr.c Normal file

File diff suppressed because it is too large Load Diff

113
pcmcia/cardmgr.h Normal file
View File

@ -0,0 +1,113 @@
/*
* cardmgr.h 1.38 2002/08/19 03:21:20
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#define MAX_SOCKS 8
#define MAX_BINDINGS 4
#define MAX_MODULES 4
typedef struct adjust_list_t {
adjust_t adj;
struct adjust_list_t *next;
} adjust_list_t;
typedef struct func_ident_t {
u_char funcid;
} func_ident_t;
typedef struct manfid_ident_t {
u_short manf;
u_short card;
} manfid_ident_t;
typedef struct vers_ident_t {
int ns;
char *pi[4];
} vers_ident_t;
typedef struct tuple_ident_t {
cisdata_t code;
long ofs;
char *info;
} tuple_ident_t;
typedef struct device_info_t {
dev_info_t dev_info;
int needs_mtd;
int modules;
char *module[MAX_MODULES];
char *opts[MAX_MODULES];
char *class;
int refs;
struct device_info_t *next;
} device_info_t;
#define VERS_1_IDENT 0x0001
#define MANFID_IDENT 0x0002
#define TUPLE_IDENT 0x0010
#define FUNC_IDENT 0x0020
#define BLANK_IDENT 0x0040
#define PCI_IDENT 0x0080
#define EXCL_IDENT 0x00f0
typedef struct card_info_t {
char *name;
int ident_type;
union {
vers_ident_t vers;
tuple_ident_t tuple;
func_ident_t func;
} id;
manfid_ident_t manfid;
int bindings;
device_info_t *device[MAX_BINDINGS];
int dev_fn[MAX_BINDINGS];
char *class[MAX_BINDINGS];
char *cis_file;
int refs;
struct card_info_t *next;
} card_info_t;
typedef struct mtd_ident_t {
char *name;
enum {
JEDEC_MTD=1, DTYPE_MTD, DEFAULT_MTD
} mtd_type;
int dtype, jedec_mfr, jedec_info;
char *module, *opts;
int refs;
struct mtd_ident_t *next;
} mtd_ident_t;
extern adjust_list_t *root_adjust;
extern device_info_t *root_device;
extern card_info_t *blank_card;
extern card_info_t *root_card, *root_func;
extern mtd_ident_t *root_mtd, *default_mtd;
int parse_configfile(char *fn);

182
pcmcia/cirrus.h Normal file
View File

@ -0,0 +1,182 @@
/*
* cirrus.h 1.10 2001/08/24 12:15:33
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#ifndef _LINUX_CIRRUS_H
#define _LINUX_CIRRUS_H
#ifndef PCI_VENDOR_ID_CIRRUS
#define PCI_VENDOR_ID_CIRRUS 0x1013
#endif
#ifndef PCI_DEVICE_ID_CIRRUS_6729
#define PCI_DEVICE_ID_CIRRUS_6729 0x1100
#endif
#ifndef PCI_DEVICE_ID_CIRRUS_6832
#define PCI_DEVICE_ID_CIRRUS_6832 0x1110
#endif
#define PD67_MISC_CTL_1 0x16 /* Misc control 1 */
#define PD67_FIFO_CTL 0x17 /* FIFO control */
#define PD67_MISC_CTL_2 0x1E /* Misc control 2 */
#define PD67_CHIP_INFO 0x1f /* Chip information */
#define PD67_ATA_CTL 0x026 /* 6730: ATA control */
#define PD67_EXT_INDEX 0x2e /* Extension index */
#define PD67_EXT_DATA 0x2f /* Extension data */
#define pd67_ext_get(s, r) \
(i365_set(s, PD67_EXT_INDEX, r), i365_get(s, PD67_EXT_DATA))
#define pd67_ext_set(s, r, v) \
(i365_set(s, PD67_EXT_INDEX, r), i365_set(s, PD67_EXT_DATA, v))
/* PD6722 extension registers -- indexed in PD67_EXT_INDEX */
#define PD67_DATA_MASK0 0x01 /* Data mask 0 */
#define PD67_DATA_MASK1 0x02 /* Data mask 1 */
#define PD67_DMA_CTL 0x03 /* DMA control */
/* PD6730 extension registers -- indexed in PD67_EXT_INDEX */
#define PD67_EXT_CTL_1 0x03 /* Extension control 1 */
#define PD67_MEM_PAGE(n) ((n)+5) /* PCI window bits 31:24 */
#define PD67_EXTERN_DATA 0x0a
#define PD67_MISC_CTL_3 0x25
#define PD67_SMB_PWR_CTL 0x26
/* I/O window address offset */
#define PD67_IO_OFF(w) (0x36+((w)<<1))
/* Timing register sets */
#define PD67_TIME_SETUP(n) (0x3a + 3*(n))
#define PD67_TIME_CMD(n) (0x3b + 3*(n))
#define PD67_TIME_RECOV(n) (0x3c + 3*(n))
/* Flags for PD67_MISC_CTL_1 */
#define PD67_MC1_5V_DET 0x01 /* 5v detect */
#define PD67_MC1_MEDIA_ENA 0x01 /* 6730: Multimedia enable */
#define PD67_MC1_VCC_3V 0x02 /* 3.3v Vcc */
#define PD67_MC1_PULSE_MGMT 0x04
#define PD67_MC1_PULSE_IRQ 0x08
#define PD67_MC1_SPKR_ENA 0x10
#define PD67_MC1_INPACK_ENA 0x80
/* Flags for PD67_FIFO_CTL */
#define PD67_FIFO_EMPTY 0x80
/* Flags for PD67_MISC_CTL_2 */
#define PD67_MC2_FREQ_BYPASS 0x01
#define PD67_MC2_DYNAMIC_MODE 0x02
#define PD67_MC2_SUSPEND 0x04
#define PD67_MC2_5V_CORE 0x08
#define PD67_MC2_LED_ENA 0x10 /* IRQ 12 is LED enable */
#define PD67_MC2_FAST_PCI 0x10 /* 6729: PCI bus > 25 MHz */
#define PD67_MC2_3STATE_BIT7 0x20 /* Floppy change bit */
#define PD67_MC2_DMA_MODE 0x40
#define PD67_MC2_IRQ15_RI 0x80 /* IRQ 15 is ring enable */
/* Flags for PD67_CHIP_INFO */
#define PD67_INFO_SLOTS 0x20 /* 0 = 1 slot, 1 = 2 slots */
#define PD67_INFO_CHIP_ID 0xc0
#define PD67_INFO_REV 0x1c
/* Fields in PD67_TIME_* registers */
#define PD67_TIME_SCALE 0xc0
#define PD67_TIME_SCALE_1 0x00
#define PD67_TIME_SCALE_16 0x40
#define PD67_TIME_SCALE_256 0x80
#define PD67_TIME_SCALE_4096 0xc0
#define PD67_TIME_MULT 0x3f
/* Fields in PD67_DMA_CTL */
#define PD67_DMA_MODE 0xc0
#define PD67_DMA_OFF 0x00
#define PD67_DMA_DREQ_INPACK 0x40
#define PD67_DMA_DREQ_WP 0x80
#define PD67_DMA_DREQ_BVD2 0xc0
#define PD67_DMA_PULLUP 0x20 /* Disable socket pullups? */
/* Fields in PD67_EXT_CTL_1 */
#define PD67_EC1_VCC_PWR_LOCK 0x01
#define PD67_EC1_AUTO_PWR_CLEAR 0x02
#define PD67_EC1_LED_ENA 0x04
#define PD67_EC1_INV_CARD_IRQ 0x08
#define PD67_EC1_INV_MGMT_IRQ 0x10
#define PD67_EC1_PULLUP_CTL 0x20
/* Fields in PD67_EXTERN_DATA */
#define PD67_EXD_VS1(s) (0x01 << ((s)<<1))
#define PD67_EXD_VS2(s) (0x02 << ((s)<<1))
/* Fields in PD67_MISC_CTL_3 */
#define PD67_MC3_IRQ_MASK 0x03
#define PD67_MC3_IRQ_PCPCI 0x00
#define PD67_MC3_IRQ_EXTERN 0x01
#define PD67_MC3_IRQ_PCIWAY 0x02
#define PD67_MC3_IRQ_PCI 0x03
#define PD67_MC3_PWR_MASK 0x0c
#define PD67_MC3_PWR_SERIAL 0x00
#define PD67_MC3_PWR_TI2202 0x08
#define PD67_MC3_PWR_SMB 0x0c
/* Register definitions for Cirrus PD6832 PCI-to-CardBus bridge */
/* PD6832 extension registers -- indexed in PD67_EXT_INDEX */
#define PD68_EXT_CTL_2 0x0b
#define PD68_PCI_SPACE 0x22
#define PD68_PCCARD_SPACE 0x23
#define PD68_WINDOW_TYPE 0x24
#define PD68_EXT_CSC 0x2e
#define PD68_MISC_CTL_4 0x2f
#define PD68_MISC_CTL_5 0x30
#define PD68_MISC_CTL_6 0x31
/* Extra flags in PD67_MISC_CTL_3 */
#define PD68_MC3_HW_SUSP 0x10
#define PD68_MC3_MM_EXPAND 0x40
#define PD68_MC3_MM_ARM 0x80
/* Bridge Control Register */
#define PD6832_BCR_MGMT_IRQ_ENA 0x0800
/* Socket Number Register */
#define PD6832_SOCKET_NUMBER 0x004c /* 8 bit */
/* Data structure for tracking vendor-specific state */
typedef struct cirrus_state_t {
u_char misc1; /* PD67_MISC_CTL_1 */
u_char misc2; /* PD67_MISC_CTL_2 */
u_char ectl1; /* PD67_EXT_CTL_1 */
u_char timer[6]; /* PD67_TIME_* */
} cirrus_state_t;
#define CIRRUS_PCIC_ID \
IS_PD6729, IS_PD6730, IS_PD6832
#define CIRRUS_PCIC_INFO \
{ "Cirrus PD6729", IS_CIRRUS|IS_PCI, ID(CIRRUS, 6729) }, \
{ "Cirrus PD6730", IS_CIRRUS|IS_PCI, PCI_VENDOR_ID_CIRRUS, -1 }, \
{ "Cirrus PD6832", IS_CIRRUS|IS_CARDBUS, ID(CIRRUS, 6832) }
#endif /* _LINUX_CIRRUS_H */

138
pcmcia/ciscode.h Normal file
View File

@ -0,0 +1,138 @@
/*
* ciscode.h 1.57 2002/11/03 20:38:14
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#ifndef _LINUX_CISCODE_H
#define _LINUX_CISCODE_H
/* Manufacturer and Product ID codes */
#define MANFID_3COM 0x0101
#define PRODID_3COM_3CXEM556 0x0035
#define PRODID_3COM_3CCFEM556 0x0556
#define PRODID_3COM_3C562 0x0562
#define MANFID_ACCTON 0x01bf
#define PRODID_ACCTON_EN2226 0x010a
#define MANFID_ADAPTEC 0x012f
#define PRODID_ADAPTEC_SCSI 0x0001
#define MANFID_ATT 0xffff
#define PRODID_ATT_KIT 0x0100
#define MANFID_CONTEC 0xc001
#define MANFID_FUJITSU 0x0004
#define PRODID_FUJITSU_MBH10302 0x0004
#define PRODID_FUJITSU_MBH10304 0x1003
#define PRODID_FUJITSU_LA501 0x2000
#define MANFID_IBM 0x00a4
#define PRODID_IBM_HOME_AND_AWAY 0x002e
#define MANFID_INTEL 0x0089
#define PRODID_INTEL_DUAL_RS232 0x0301
#define PRODID_INTEL_2PLUS 0x8422
#define MANFID_KME 0x0032
#define PRODID_KME_KXLC005_A 0x0704
#define PRODID_KME_KXLC005_B 0x2904
#define MANFID_LINKSYS 0x0143
#define PRODID_LINKSYS_PCMLM28 0xc0ab
#define PRODID_LINKSYS_3400 0x3341
#define MANFID_MEGAHERTZ 0x0102
#define PRODID_MEGAHERTZ_VARIOUS 0x0000
#define PRODID_MEGAHERTZ_EM3288 0x0006
#define MANFID_MACNICA 0xc00b
#define MANFID_MOTOROLA 0x0109
#define PRODID_MOTOROLA_MARINER 0x0501
#define MANFID_NATINST 0x010b
#define PRODID_NATINST_QUAD_RS232 0xd180
#define MANFID_NEW_MEDIA 0x0057
#define MANFID_NOKIA 0x0124
#define PRODID_NOKIA_CARDPHONE 0x0900
#define MANFID_OLICOM 0x0121
#define PRODID_OLICOM_OC2231 0x3122
#define PRODID_OLICOM_OC2232 0x3222
#define MANFID_OMEGA 0x0137
#define PRODID_OMEGA_QSP_100 0x0025
#define MANFID_OSITECH 0x0140
#define PRODID_OSITECH_JACK_144 0x0001
#define PRODID_OSITECH_JACK_288 0x0002
#define PRODID_OSITECH_JACK_336 0x0007
#define PRODID_OSITECH_SEVEN 0x0008
#define MANFID_OXSEMI 0x0279
#define MANFID_PIONEER 0x000b
#define MANFID_PSION 0x016c
#define PRODID_PSION_NET100 0x0023
#define MANFID_QUATECH 0x0137
#define PRODID_QUATECH_SPP100 0x0003
#define PRODID_QUATECH_DUAL_RS232 0x0012
#define PRODID_QUATECH_DUAL_RS232_D1 0x0007
#define PRODID_QUATECH_DUAL_RS232_D2 0x0052
#define PRODID_QUATECH_QUAD_RS232 0x001b
#define PRODID_QUATECH_DUAL_RS422 0x000e
#define PRODID_QUATECH_QUAD_RS422 0x0045
#define MANFID_SMC 0x0108
#define PRODID_SMC_ETHER 0x0105
#define MANFID_SOCKET 0x0104
#define PRODID_SOCKET_DUAL_RS232 0x0006
#define PRODID_SOCKET_EIO 0x000a
#define PRODID_SOCKET_LPE 0x000d
#define PRODID_SOCKET_LPE_CF 0x0075
#define MANFID_SUNDISK 0x0045
#define MANFID_TDK 0x0105
#define PRODID_TDK_CF010 0x0900
#define PRODID_TDK_GN3410 0x4815
#define MANFID_TOSHIBA 0x0098
#define MANFID_UNGERMANN 0x02c0
#define MANFID_XIRCOM 0x0105
#endif /* _LINUX_CISCODE_H */

135
pcmcia/cisreg.h Normal file
View File

@ -0,0 +1,135 @@
/*
* cisreg.h 1.18 2001/08/24 12:16:12
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#ifndef _LINUX_CISREG_H
#define _LINUX_CISREG_H
/*
* Offsets from ConfigBase for CIS registers
*/
#define CISREG_COR 0x00
#define CISREG_CCSR 0x02
#define CISREG_PRR 0x04
#define CISREG_SCR 0x06
#define CISREG_ESR 0x08
#define CISREG_IOBASE_0 0x0a
#define CISREG_IOBASE_1 0x0c
#define CISREG_IOBASE_2 0x0e
#define CISREG_IOBASE_3 0x10
#define CISREG_IOSIZE 0x12
/*
* Configuration Option Register
*/
#define COR_CONFIG_MASK 0x3f
#define COR_MFC_CONFIG_MASK 0x38
#define COR_FUNC_ENA 0x01
#define COR_ADDR_DECODE 0x02
#define COR_IREQ_ENA 0x04
#define COR_LEVEL_REQ 0x40
#define COR_SOFT_RESET 0x80
/*
* Card Configuration and Status Register
*/
#define CCSR_INTR_ACK 0x01
#define CCSR_INTR_PENDING 0x02
#define CCSR_POWER_DOWN 0x04
#define CCSR_AUDIO_ENA 0x08
#define CCSR_IOIS8 0x20
#define CCSR_SIGCHG_ENA 0x40
#define CCSR_CHANGED 0x80
/*
* Pin Replacement Register
*/
#define PRR_WP_STATUS 0x01
#define PRR_READY_STATUS 0x02
#define PRR_BVD2_STATUS 0x04
#define PRR_BVD1_STATUS 0x08
#define PRR_WP_EVENT 0x10
#define PRR_READY_EVENT 0x20
#define PRR_BVD2_EVENT 0x40
#define PRR_BVD1_EVENT 0x80
/*
* Socket and Copy Register
*/
#define SCR_SOCKET_NUM 0x0f
#define SCR_COPY_NUM 0x70
/*
* Extended Status Register
*/
#define ESR_REQ_ATTN_ENA 0x01
#define ESR_REQ_ATTN 0x10
/*
* CardBus Function Status Registers
*/
#define CBFN_EVENT 0x00
#define CBFN_MASK 0x04
#define CBFN_STATE 0x08
#define CBFN_FORCE 0x0c
/*
* These apply to all the CardBus function registers
*/
#define CBFN_WP 0x0001
#define CBFN_READY 0x0002
#define CBFN_BVD2 0x0004
#define CBFN_BVD1 0x0008
#define CBFN_GWAKE 0x0010
#define CBFN_INTR 0x8000
/*
* Extra bits in the Function Event Mask Register
*/
#define FEMR_BAM_ENA 0x0020
#define FEMR_PWM_ENA 0x0040
#define FEMR_WKUP_MASK 0x4000
/*
* Indirect Addressing Registers for Zoomed Video: these are addresses
* in common memory space
*/
#define CISREG_ICTRL0 0x02 /* control registers */
#define CISREG_ICTRL1 0x03
#define CISREG_IADDR0 0x04 /* address registers */
#define CISREG_IADDR1 0x05
#define CISREG_IADDR2 0x06
#define CISREG_IADDR3 0x07
#define CISREG_IDATA0 0x08 /* data registers */
#define CISREG_IDATA1 0x09
#define ICTRL0_COMMON 0x01
#define ICTRL0_AUTOINC 0x02
#define ICTRL0_BYTEGRAN 0x04
#endif /* _LINUX_CISREG_H */

604
pcmcia/cistpl.h Normal file
View File

@ -0,0 +1,604 @@
/*
* cistpl.h 1.35 2001/08/24 12:16:12
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#ifndef _LINUX_CISTPL_H
#define _LINUX_CISTPL_H
#define CISTPL_NULL 0x00
#define CISTPL_DEVICE 0x01
#define CISTPL_LONGLINK_CB 0x02
#define CISTPL_INDIRECT 0x03
#define CISTPL_CONFIG_CB 0x04
#define CISTPL_CFTABLE_ENTRY_CB 0x05
#define CISTPL_LONGLINK_MFC 0x06
#define CISTPL_BAR 0x07
#define CISTPL_PWR_MGMNT 0x08
#define CISTPL_EXTDEVICE 0x09
#define CISTPL_CHECKSUM 0x10
#define CISTPL_LONGLINK_A 0x11
#define CISTPL_LONGLINK_C 0x12
#define CISTPL_LINKTARGET 0x13
#define CISTPL_NO_LINK 0x14
#define CISTPL_VERS_1 0x15
#define CISTPL_ALTSTR 0x16
#define CISTPL_DEVICE_A 0x17
#define CISTPL_JEDEC_C 0x18
#define CISTPL_JEDEC_A 0x19
#define CISTPL_CONFIG 0x1a
#define CISTPL_CFTABLE_ENTRY 0x1b
#define CISTPL_DEVICE_OC 0x1c
#define CISTPL_DEVICE_OA 0x1d
#define CISTPL_DEVICE_GEO 0x1e
#define CISTPL_DEVICE_GEO_A 0x1f
#define CISTPL_MANFID 0x20
#define CISTPL_FUNCID 0x21
#define CISTPL_FUNCE 0x22
#define CISTPL_SWIL 0x23
#define CISTPL_END 0xff
/* Layer 2 tuples */
#define CISTPL_VERS_2 0x40
#define CISTPL_FORMAT 0x41
#define CISTPL_GEOMETRY 0x42
#define CISTPL_BYTEORDER 0x43
#define CISTPL_DATE 0x44
#define CISTPL_BATTERY 0x45
#define CISTPL_FORMAT_A 0x47
/* Layer 3 tuples */
#define CISTPL_ORG 0x46
#define CISTPL_SPCL 0x90
typedef struct cistpl_longlink_t {
u_int addr;
} cistpl_longlink_t;
typedef struct cistpl_checksum_t {
u_short addr;
u_short len;
u_char sum;
} cistpl_checksum_t;
#define CISTPL_MAX_FUNCTIONS 8
#define CISTPL_MFC_ATTR 0x00
#define CISTPL_MFC_COMMON 0x01
typedef struct cistpl_longlink_mfc_t {
u_char nfn;
struct {
u_char space;
u_int addr;
} fn[CISTPL_MAX_FUNCTIONS];
} cistpl_longlink_mfc_t;
#define CISTPL_MAX_ALTSTR_STRINGS 4
typedef struct cistpl_altstr_t {
u_char ns;
u_char ofs[CISTPL_MAX_ALTSTR_STRINGS];
char str[254];
} cistpl_altstr_t;
#define CISTPL_DTYPE_NULL 0x00
#define CISTPL_DTYPE_ROM 0x01
#define CISTPL_DTYPE_OTPROM 0x02
#define CISTPL_DTYPE_EPROM 0x03
#define CISTPL_DTYPE_EEPROM 0x04
#define CISTPL_DTYPE_FLASH 0x05
#define CISTPL_DTYPE_SRAM 0x06
#define CISTPL_DTYPE_DRAM 0x07
#define CISTPL_DTYPE_FUNCSPEC 0x0d
#define CISTPL_DTYPE_EXTEND 0x0e
#define CISTPL_MAX_DEVICES 4
typedef struct cistpl_device_t {
u_char ndev;
struct {
u_char type;
u_char wp;
u_int speed;
u_int size;
} dev[CISTPL_MAX_DEVICES];
} cistpl_device_t;
#define CISTPL_DEVICE_MWAIT 0x01
#define CISTPL_DEVICE_3VCC 0x02
typedef struct cistpl_device_o_t {
u_char flags;
cistpl_device_t device;
} cistpl_device_o_t;
#define CISTPL_VERS_1_MAX_PROD_STRINGS 4
typedef struct cistpl_vers_1_t {
u_char major;
u_char minor;
u_char ns;
u_char ofs[CISTPL_VERS_1_MAX_PROD_STRINGS];
char str[254];
} cistpl_vers_1_t;
typedef struct cistpl_jedec_t {
u_char nid;
struct {
u_char mfr;
u_char info;
} id[CISTPL_MAX_DEVICES];
} cistpl_jedec_t;
typedef struct cistpl_manfid_t {
u_short manf;
u_short card;
} cistpl_manfid_t;
#define CISTPL_FUNCID_MULTI 0x00
#define CISTPL_FUNCID_MEMORY 0x01
#define CISTPL_FUNCID_SERIAL 0x02
#define CISTPL_FUNCID_PARALLEL 0x03
#define CISTPL_FUNCID_FIXED 0x04
#define CISTPL_FUNCID_VIDEO 0x05
#define CISTPL_FUNCID_NETWORK 0x06
#define CISTPL_FUNCID_AIMS 0x07
#define CISTPL_FUNCID_SCSI 0x08
#define CISTPL_SYSINIT_POST 0x01
#define CISTPL_SYSINIT_ROM 0x02
typedef struct cistpl_funcid_t {
u_char func;
u_char sysinit;
} cistpl_funcid_t;
typedef struct cistpl_funce_t {
u_char type;
u_char data[0];
} cistpl_funce_t;
/*======================================================================
Modem Function Extension Tuples
======================================================================*/
#define CISTPL_FUNCE_SERIAL_IF 0x00
#define CISTPL_FUNCE_SERIAL_CAP 0x01
#define CISTPL_FUNCE_SERIAL_SERV_DATA 0x02
#define CISTPL_FUNCE_SERIAL_SERV_FAX 0x03
#define CISTPL_FUNCE_SERIAL_SERV_VOICE 0x04
#define CISTPL_FUNCE_SERIAL_CAP_DATA 0x05
#define CISTPL_FUNCE_SERIAL_CAP_FAX 0x06
#define CISTPL_FUNCE_SERIAL_CAP_VOICE 0x07
#define CISTPL_FUNCE_SERIAL_IF_DATA 0x08
#define CISTPL_FUNCE_SERIAL_IF_FAX 0x09
#define CISTPL_FUNCE_SERIAL_IF_VOICE 0x0a
/* UART identification */
#define CISTPL_SERIAL_UART_8250 0x00
#define CISTPL_SERIAL_UART_16450 0x01
#define CISTPL_SERIAL_UART_16550 0x02
#define CISTPL_SERIAL_UART_8251 0x03
#define CISTPL_SERIAL_UART_8530 0x04
#define CISTPL_SERIAL_UART_85230 0x05
/* UART capabilities */
#define CISTPL_SERIAL_UART_SPACE 0x01
#define CISTPL_SERIAL_UART_MARK 0x02
#define CISTPL_SERIAL_UART_ODD 0x04
#define CISTPL_SERIAL_UART_EVEN 0x08
#define CISTPL_SERIAL_UART_5BIT 0x01
#define CISTPL_SERIAL_UART_6BIT 0x02
#define CISTPL_SERIAL_UART_7BIT 0x04
#define CISTPL_SERIAL_UART_8BIT 0x08
#define CISTPL_SERIAL_UART_1STOP 0x10
#define CISTPL_SERIAL_UART_MSTOP 0x20
#define CISTPL_SERIAL_UART_2STOP 0x40
typedef struct cistpl_serial_t {
u_char uart_type;
u_char uart_cap_0;
u_char uart_cap_1;
} cistpl_serial_t;
typedef struct cistpl_modem_cap_t {
u_char flow;
u_char cmd_buf;
u_char rcv_buf_0, rcv_buf_1, rcv_buf_2;
u_char xmit_buf_0, xmit_buf_1, xmit_buf_2;
} cistpl_modem_cap_t;
#define CISTPL_SERIAL_MOD_103 0x01
#define CISTPL_SERIAL_MOD_V21 0x02
#define CISTPL_SERIAL_MOD_V23 0x04
#define CISTPL_SERIAL_MOD_V22 0x08
#define CISTPL_SERIAL_MOD_212A 0x10
#define CISTPL_SERIAL_MOD_V22BIS 0x20
#define CISTPL_SERIAL_MOD_V26 0x40
#define CISTPL_SERIAL_MOD_V26BIS 0x80
#define CISTPL_SERIAL_MOD_V27BIS 0x01
#define CISTPL_SERIAL_MOD_V29 0x02
#define CISTPL_SERIAL_MOD_V32 0x04
#define CISTPL_SERIAL_MOD_V32BIS 0x08
#define CISTPL_SERIAL_MOD_V34 0x10
#define CISTPL_SERIAL_ERR_MNP2_4 0x01
#define CISTPL_SERIAL_ERR_V42_LAPM 0x02
#define CISTPL_SERIAL_CMPR_V42BIS 0x01
#define CISTPL_SERIAL_CMPR_MNP5 0x02
#define CISTPL_SERIAL_CMD_AT1 0x01
#define CISTPL_SERIAL_CMD_AT2 0x02
#define CISTPL_SERIAL_CMD_AT3 0x04
#define CISTPL_SERIAL_CMD_MNP_AT 0x08
#define CISTPL_SERIAL_CMD_V25BIS 0x10
#define CISTPL_SERIAL_CMD_V25A 0x20
#define CISTPL_SERIAL_CMD_DMCL 0x40
typedef struct cistpl_data_serv_t {
u_char max_data_0;
u_char max_data_1;
u_char modulation_0;
u_char modulation_1;
u_char error_control;
u_char compression;
u_char cmd_protocol;
u_char escape;
u_char encrypt;
u_char misc_features;
u_char ccitt_code[0];
} cistpl_data_serv_t;
typedef struct cistpl_fax_serv_t {
u_char max_data_0;
u_char max_data_1;
u_char modulation;
u_char encrypt;
u_char features_0;
u_char features_1;
u_char ccitt_code[0];
} cistpl_fax_serv_t;
typedef struct cistpl_voice_serv_t {
u_char max_data_0;
u_char max_data_1;
} cistpl_voice_serv_t;
/*======================================================================
LAN Function Extension Tuples
======================================================================*/
#define CISTPL_FUNCE_LAN_TECH 0x01
#define CISTPL_FUNCE_LAN_SPEED 0x02
#define CISTPL_FUNCE_LAN_MEDIA 0x03
#define CISTPL_FUNCE_LAN_NODE_ID 0x04
#define CISTPL_FUNCE_LAN_CONNECTOR 0x05
/* LAN technologies */
#define CISTPL_LAN_TECH_ARCNET 0x01
#define CISTPL_LAN_TECH_ETHERNET 0x02
#define CISTPL_LAN_TECH_TOKENRING 0x03
#define CISTPL_LAN_TECH_LOCALTALK 0x04
#define CISTPL_LAN_TECH_FDDI 0x05
#define CISTPL_LAN_TECH_ATM 0x06
#define CISTPL_LAN_TECH_WIRELESS 0x07
typedef struct cistpl_lan_tech_t {
u_char tech;
} cistpl_lan_tech_t;
typedef struct cistpl_lan_speed_t {
u_int speed;
} cistpl_lan_speed_t;
/* LAN media definitions */
#define CISTPL_LAN_MEDIA_UTP 0x01
#define CISTPL_LAN_MEDIA_STP 0x02
#define CISTPL_LAN_MEDIA_THIN_COAX 0x03
#define CISTPL_LAN_MEDIA_THICK_COAX 0x04
#define CISTPL_LAN_MEDIA_FIBER 0x05
#define CISTPL_LAN_MEDIA_900MHZ 0x06
#define CISTPL_LAN_MEDIA_2GHZ 0x07
#define CISTPL_LAN_MEDIA_5GHZ 0x08
#define CISTPL_LAN_MEDIA_DIFF_IR 0x09
#define CISTPL_LAN_MEDIA_PTP_IR 0x0a
typedef struct cistpl_lan_media_t {
u_char media;
} cistpl_lan_media_t;
typedef struct cistpl_lan_node_id_t {
u_char nb;
u_char id[16];
} cistpl_lan_node_id_t;
typedef struct cistpl_lan_connector_t {
u_char code;
} cistpl_lan_connector_t;
/*======================================================================
IDE Function Extension Tuples
======================================================================*/
#define CISTPL_IDE_INTERFACE 0x01
typedef struct cistpl_ide_interface_t {
u_char interface;
} cistpl_ide_interface_t;
/* First feature byte */
#define CISTPL_IDE_SILICON 0x04
#define CISTPL_IDE_UNIQUE 0x08
#define CISTPL_IDE_DUAL 0x10
/* Second feature byte */
#define CISTPL_IDE_HAS_SLEEP 0x01
#define CISTPL_IDE_HAS_STANDBY 0x02
#define CISTPL_IDE_HAS_IDLE 0x04
#define CISTPL_IDE_LOW_POWER 0x08
#define CISTPL_IDE_REG_INHIBIT 0x10
#define CISTPL_IDE_HAS_INDEX 0x20
#define CISTPL_IDE_IOIS16 0x40
typedef struct cistpl_ide_feature_t {
u_char feature1;
u_char feature2;
} cistpl_ide_feature_t;
#define CISTPL_FUNCE_IDE_IFACE 0x01
#define CISTPL_FUNCE_IDE_MASTER 0x02
#define CISTPL_FUNCE_IDE_SLAVE 0x03
/*======================================================================
Configuration Table Entries
======================================================================*/
#define CISTPL_BAR_SPACE 0x07
#define CISTPL_BAR_SPACE_IO 0x10
#define CISTPL_BAR_PREFETCH 0x20
#define CISTPL_BAR_CACHEABLE 0x40
#define CISTPL_BAR_1MEG_MAP 0x80
typedef struct cistpl_bar_t {
u_char attr;
u_int size;
} cistpl_bar_t;
typedef struct cistpl_config_t {
u_char last_idx;
u_int base;
u_int rmask[4];
u_char subtuples;
} cistpl_config_t;
/* These are bits in the 'present' field, and indices in 'param' */
#define CISTPL_POWER_VNOM 0
#define CISTPL_POWER_VMIN 1
#define CISTPL_POWER_VMAX 2
#define CISTPL_POWER_ISTATIC 3
#define CISTPL_POWER_IAVG 4
#define CISTPL_POWER_IPEAK 5
#define CISTPL_POWER_IDOWN 6
#define CISTPL_POWER_HIGHZ_OK 0x01
#define CISTPL_POWER_HIGHZ_REQ 0x02
typedef struct cistpl_power_t {
u_char present;
u_char flags;
u_int param[7];
} cistpl_power_t;
typedef struct cistpl_timing_t {
u_int wait, waitscale;
u_int ready, rdyscale;
u_int reserved, rsvscale;
} cistpl_timing_t;
#define CISTPL_IO_LINES_MASK 0x1f
#define CISTPL_IO_8BIT 0x20
#define CISTPL_IO_16BIT 0x40
#define CISTPL_IO_RANGE 0x80
#define CISTPL_IO_MAX_WIN 16
typedef struct cistpl_io_t {
u_char flags;
u_char nwin;
struct {
u_int base;
u_int len;
} win[CISTPL_IO_MAX_WIN];
} cistpl_io_t;
typedef struct cistpl_irq_t {
u_int IRQInfo1;
u_int IRQInfo2;
} cistpl_irq_t;
#define CISTPL_MEM_MAX_WIN 8
typedef struct cistpl_mem_t {
u_char flags;
u_char nwin;
struct {
u_int len;
u_int card_addr;
u_int host_addr;
} win[CISTPL_MEM_MAX_WIN];
} cistpl_mem_t;
#define CISTPL_CFTABLE_DEFAULT 0x0001
#define CISTPL_CFTABLE_BVDS 0x0002
#define CISTPL_CFTABLE_WP 0x0004
#define CISTPL_CFTABLE_RDYBSY 0x0008
#define CISTPL_CFTABLE_MWAIT 0x0010
#define CISTPL_CFTABLE_AUDIO 0x0800
#define CISTPL_CFTABLE_READONLY 0x1000
#define CISTPL_CFTABLE_PWRDOWN 0x2000
typedef struct cistpl_cftable_entry_t {
u_char index;
u_short flags;
u_char interface;
cistpl_power_t vcc, vpp1, vpp2;
cistpl_timing_t timing;
cistpl_io_t io;
cistpl_irq_t irq;
cistpl_mem_t mem;
u_char subtuples;
} cistpl_cftable_entry_t;
#define CISTPL_CFTABLE_MASTER 0x000100
#define CISTPL_CFTABLE_INVALIDATE 0x000200
#define CISTPL_CFTABLE_VGA_PALETTE 0x000400
#define CISTPL_CFTABLE_PARITY 0x000800
#define CISTPL_CFTABLE_WAIT 0x001000
#define CISTPL_CFTABLE_SERR 0x002000
#define CISTPL_CFTABLE_FAST_BACK 0x004000
#define CISTPL_CFTABLE_BINARY_AUDIO 0x010000
#define CISTPL_CFTABLE_PWM_AUDIO 0x020000
typedef struct cistpl_cftable_entry_cb_t {
u_char index;
u_int flags;
cistpl_power_t vcc, vpp1, vpp2;
u_char io;
cistpl_irq_t irq;
u_char mem;
u_char subtuples;
} cistpl_cftable_entry_cb_t;
typedef struct cistpl_device_geo_t {
u_char ngeo;
struct {
u_char buswidth;
u_int erase_block;
u_int read_block;
u_int write_block;
u_int partition;
u_int interleave;
} geo[CISTPL_MAX_DEVICES];
} cistpl_device_geo_t;
typedef struct cistpl_vers_2_t {
u_char vers;
u_char comply;
u_short dindex;
u_char vspec8, vspec9;
u_char nhdr;
u_char vendor, info;
char str[244];
} cistpl_vers_2_t;
typedef struct cistpl_org_t {
u_char data_org;
char desc[30];
} cistpl_org_t;
#define CISTPL_ORG_FS 0x00
#define CISTPL_ORG_APPSPEC 0x01
#define CISTPL_ORG_XIP 0x02
typedef struct cistpl_format_t {
u_char type;
u_char edc;
u_int offset;
u_int length;
} cistpl_format_t;
#define CISTPL_FORMAT_DISK 0x00
#define CISTPL_FORMAT_MEM 0x01
#define CISTPL_EDC_NONE 0x00
#define CISTPL_EDC_CKSUM 0x01
#define CISTPL_EDC_CRC 0x02
#define CISTPL_EDC_PCC 0x03
typedef union cisparse_t {
cistpl_device_t device;
cistpl_checksum_t checksum;
cistpl_longlink_t longlink;
cistpl_longlink_mfc_t longlink_mfc;
cistpl_vers_1_t version_1;
cistpl_altstr_t altstr;
cistpl_jedec_t jedec;
cistpl_manfid_t manfid;
cistpl_funcid_t funcid;
cistpl_funce_t funce;
cistpl_bar_t bar;
cistpl_config_t config;
cistpl_cftable_entry_t cftable_entry;
cistpl_cftable_entry_cb_t cftable_entry_cb;
cistpl_device_geo_t device_geo;
cistpl_vers_2_t vers_2;
cistpl_org_t org;
cistpl_format_t format;
} cisparse_t;
typedef struct tuple_t {
u_int Attributes;
cisdata_t DesiredTuple;
u_int Flags; /* internal use */
u_int LinkOffset; /* internal use */
u_int CISOffset; /* internal use */
cisdata_t TupleCode;
cisdata_t TupleLink;
cisdata_t TupleOffset;
cisdata_t TupleDataMax;
cisdata_t TupleDataLen;
cisdata_t *TupleData;
} tuple_t;
/* Special cisdata_t value */
#define RETURN_FIRST_TUPLE 0xff
/* Attributes for tuple calls */
#define TUPLE_RETURN_LINK 0x01
#define TUPLE_RETURN_COMMON 0x02
/* For ValidateCIS */
typedef struct cisinfo_t {
u_int Chains;
} cisinfo_t;
#define CISTPL_MAX_CIS_SIZE 0x200
/* For ReplaceCIS */
typedef struct cisdump_t {
u_int Length;
cisdata_t Data[CISTPL_MAX_CIS_SIZE];
} cisdump_t;
#endif /* LINUX_CISTPL_H */

59
pcmcia/config.h Normal file
View File

@ -0,0 +1,59 @@
/*
Automatically generated by 'make config' -- don't edit!
*/
#ifndef _PCMCIA_CONFIG_H
#define _PCMCIA_CONFIG_H
#define AUTOCONF_INCLUDED
#define __IN_PCMCIA_PACKAGE__
#define LINUX "/home/gc/rpm/BUILD/linux"
#define PREFIX "/home/gc/rpm/tmp/kernel-2.4.0-build"
#define CC "/usr/bin/kgcc"
#define LD "ld"
#define KFLAGS ""
#define UFLAGS ""
#define PCDEBUG ""
#define USE_PM 1
#define UNSAFE_TOOLS 1
#define CONFIG_CARDBUS 1
#undef CONFIG_PNP_BIOS
#define MODDIR "/lib/modules/2.4.0-6mdk"
/* Options from /home/gc/rpm/BUILD/linux/.config */
#define CONFIG_MODULES 1
#undef CONFIG_PCMCIA
#undef CONFIG_SMP
#define CONFIG_PCI 1
#define CONFIG_PCI_QUIRKS 1
#define CONFIG_PM 1
#define CONFIG_SCSI 1
#define CONFIG_IEEE1394 1
#define CONFIG_INET 1
#define CONFIG_NET_PCMCIA_RADIO 1
#define CONFIG_TR 1
#undef CONFIG_NET_FASTROUTE
#undef CONFIG_NET_DIVERT
#define CONFIG_MODVERSIONS 1
#define CONFIG_X86_L1_CACHE_BYTES 32
#define CONFIG_X86_L1_CACHE_SHIFT 5
#define CONFIG_PROC_FS 1
#define ARCH "i386"
#define HOST_ARCH "i386"
#define AFLAGS ""
#define CONFIG_ISA 1
#define CONFIG_UID16 1
#define UTS_RELEASE "2.4.0-6mdk"
#define UTS_VERSION "#1 Wed Jan 24 16:10:16 CET 2001"
#define LINUX_VERSION_CODE 132096
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
#define HAS_PROC_BUS 1
#define SYSV_INIT 1
#define RC_DIR "/etc/rc.d"
#undef HAS_FORMS
#define MANDIR "/usr/share/man"
#define XMANDIR "/usr/X11R6/man"
#endif /* _PCMCIA_CONFIG_H */

441
pcmcia/cs.h Normal file
View File

@ -0,0 +1,441 @@
/*
* cs.h 1.74 2001/10/04 03:15:22
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#ifndef _LINUX_CS_H
#define _LINUX_CS_H
/* For AccessConfigurationRegister */
typedef struct conf_reg_t {
u_char Function;
u_int Action;
off_t Offset;
u_int Value;
} conf_reg_t;
/* Actions */
#define CS_READ 1
#define CS_WRITE 2
/* for AdjustResourceInfo */
typedef struct adjust_t {
u_int Action;
u_int Resource;
u_int Attributes;
union {
struct memory {
u_long Base;
u_long Size;
} memory;
struct io {
ioaddr_t BasePort;
ioaddr_t NumPorts;
u_int IOAddrLines;
} io;
struct irq {
u_int IRQ;
} irq;
} resource;
} adjust_t;
/* Action field */
#define REMOVE_MANAGED_RESOURCE 1
#define ADD_MANAGED_RESOURCE 2
#define GET_FIRST_MANAGED_RESOURCE 3
#define GET_NEXT_MANAGED_RESOURCE 4
/* Resource field */
#define RES_MEMORY_RANGE 1
#define RES_IO_RANGE 2
#define RES_IRQ 3
/* Attribute field */
#define RES_IRQ_TYPE 0x03
#define RES_IRQ_TYPE_EXCLUSIVE 0
#define RES_IRQ_TYPE_TIME 1
#define RES_IRQ_TYPE_DYNAMIC 2
#define RES_IRQ_CSC 0x04
#define RES_SHARED 0x08
#define RES_RESERVED 0x10
#define RES_ALLOCATED 0x20
#define RES_REMOVED 0x40
typedef struct servinfo_t {
char Signature[2];
u_int Count;
u_int Revision;
u_int CSLevel;
char *VendorString;
} servinfo_t;
typedef struct event_callback_args_t {
client_handle_t client_handle;
void *info;
void *mtdrequest;
void *buffer;
void *misc;
void *client_data;
struct bus_operations *bus;
} event_callback_args_t;
/* for GetConfigurationInfo */
typedef struct config_info_t {
u_char Function;
u_int Attributes;
u_int Vcc, Vpp1, Vpp2;
u_int IntType;
u_int ConfigBase;
u_char Status, Pin, Copy, Option, ExtStatus;
u_int Present;
u_int CardValues;
u_int AssignedIRQ;
u_int IRQAttributes;
ioaddr_t BasePort1;
ioaddr_t NumPorts1;
u_int Attributes1;
ioaddr_t BasePort2;
ioaddr_t NumPorts2;
u_int Attributes2;
u_int IOAddrLines;
} config_info_t;
/* For CardValues field */
#define CV_OPTION_VALUE 0x01
#define CV_STATUS_VALUE 0x02
#define CV_PIN_REPLACEMENT 0x04
#define CV_COPY_VALUE 0x08
#define CV_EXT_STATUS 0x10
/* For GetFirst/NextClient */
typedef struct client_req_t {
socket_t Socket;
u_int Attributes;
} client_req_t;
#define CLIENT_THIS_SOCKET 0x01
/* For RegisterClient */
typedef struct client_reg_t {
dev_info_t *dev_info;
u_int Attributes;
u_int EventMask;
int (*event_handler)(event_t event, int priority,
event_callback_args_t *);
event_callback_args_t event_callback_args;
u_int Version;
} client_reg_t;
/* ModifyConfiguration */
typedef struct modconf_t {
u_int Attributes;
u_int Vcc, Vpp1, Vpp2;
} modconf_t;
/* Attributes for ModifyConfiguration */
#define CONF_IRQ_CHANGE_VALID 0x100
#define CONF_VCC_CHANGE_VALID 0x200
#define CONF_VPP1_CHANGE_VALID 0x400
#define CONF_VPP2_CHANGE_VALID 0x800
/* For RequestConfiguration */
typedef struct config_req_t {
u_int Attributes;
u_int Vcc, Vpp1, Vpp2;
u_int IntType;
u_int ConfigBase;
u_char Status, Pin, Copy, ExtStatus;
u_char ConfigIndex;
u_int Present;
} config_req_t;
/* Attributes for RequestConfiguration */
#define CONF_ENABLE_IRQ 0x01
#define CONF_ENABLE_DMA 0x02
#define CONF_ENABLE_SPKR 0x04
#define CONF_VALID_CLIENT 0x100
/* IntType field */
#define INT_MEMORY 0x01
#define INT_MEMORY_AND_IO 0x02
#define INT_CARDBUS 0x04
#define INT_ZOOMED_VIDEO 0x08
/* For RequestIO and ReleaseIO */
typedef struct io_req_t {
ioaddr_t BasePort1;
ioaddr_t NumPorts1;
u_int Attributes1;
ioaddr_t BasePort2;
ioaddr_t NumPorts2;
u_int Attributes2;
u_int IOAddrLines;
} io_req_t;
/* Attributes for RequestIO and ReleaseIO */
#define IO_SHARED 0x01
#define IO_FIRST_SHARED 0x02
#define IO_FORCE_ALIAS_ACCESS 0x04
#define IO_DATA_PATH_WIDTH 0x18
#define IO_DATA_PATH_WIDTH_8 0x00
#define IO_DATA_PATH_WIDTH_16 0x08
#define IO_DATA_PATH_WIDTH_AUTO 0x10
/* For RequestIRQ and ReleaseIRQ */
typedef struct irq_req_t {
u_int Attributes;
u_int AssignedIRQ;
u_int IRQInfo1, IRQInfo2;
void *Handler;
void *Instance;
} irq_req_t;
/* Attributes for RequestIRQ and ReleaseIRQ */
#define IRQ_TYPE 0x03
#define IRQ_TYPE_EXCLUSIVE 0x00
#define IRQ_TYPE_TIME 0x01
#define IRQ_TYPE_DYNAMIC_SHARING 0x02
#define IRQ_FORCED_PULSE 0x04
#define IRQ_FIRST_SHARED 0x08
#define IRQ_HANDLE_PRESENT 0x10
#define IRQ_PULSE_ALLOCATED 0x100
/* Bits in IRQInfo1 field */
#define IRQ_MASK 0x0f
#define IRQ_NMI_ID 0x01
#define IRQ_IOCK_ID 0x02
#define IRQ_BERR_ID 0x04
#define IRQ_VEND_ID 0x08
#define IRQ_INFO2_VALID 0x10
#define IRQ_LEVEL_ID 0x20
#define IRQ_PULSE_ID 0x40
#define IRQ_SHARE_ID 0x80
typedef struct eventmask_t {
u_int Attributes;
u_int EventMask;
} eventmask_t;
#define CONF_EVENT_MASK_VALID 0x01
/* Configuration registers present */
#define PRESENT_OPTION 0x001
#define PRESENT_STATUS 0x002
#define PRESENT_PIN_REPLACE 0x004
#define PRESENT_COPY 0x008
#define PRESENT_EXT_STATUS 0x010
#define PRESENT_IOBASE_0 0x020
#define PRESENT_IOBASE_1 0x040
#define PRESENT_IOBASE_2 0x080
#define PRESENT_IOBASE_3 0x100
#define PRESENT_IOSIZE 0x200
/* For GetMemPage, MapMemPage */
typedef struct memreq_t {
u_int CardOffset;
page_t Page;
} memreq_t;
/* For ModifyWindow */
typedef struct modwin_t {
u_int Attributes;
u_int AccessSpeed;
} modwin_t;
/* For RequestWindow */
typedef struct win_req_t {
u_int Attributes;
u_long Base;
u_int Size;
u_int AccessSpeed;
} win_req_t;
/* Attributes for RequestWindow */
#define WIN_ADDR_SPACE 0x0001
#define WIN_ADDR_SPACE_MEM 0x0000
#define WIN_ADDR_SPACE_IO 0x0001
#define WIN_MEMORY_TYPE 0x0002
#define WIN_MEMORY_TYPE_CM 0x0000
#define WIN_MEMORY_TYPE_AM 0x0002
#define WIN_ENABLE 0x0004
#define WIN_DATA_WIDTH 0x0018
#define WIN_DATA_WIDTH_8 0x0000
#define WIN_DATA_WIDTH_16 0x0008
#define WIN_DATA_WIDTH_32 0x0010
#define WIN_PAGED 0x0020
#define WIN_SHARED 0x0040
#define WIN_FIRST_SHARED 0x0080
#define WIN_USE_WAIT 0x0100
#define WIN_STRICT_ALIGN 0x0200
#define WIN_MAP_BELOW_1MB 0x0400
#define WIN_PREFETCH 0x0800
#define WIN_CACHEABLE 0x1000
#define WIN_BAR_MASK 0xe000
#define WIN_BAR_SHIFT 13
/* Attributes for RegisterClient */
#define INFO_MASTER_CLIENT 0x01
#define INFO_IO_CLIENT 0x02
#define INFO_MTD_CLIENT 0x04
#define INFO_MEM_CLIENT 0x08
#define MAX_NUM_CLIENTS 3
#define INFO_CARD_SHARE 0x10
#define INFO_CARD_EXCL 0x20
typedef struct cs_status_t {
u_char Function;
event_t CardState;
event_t SocketState;
} cs_status_t;
typedef struct error_info_t {
int func;
int retcode;
} error_info_t;
/* Special stuff for binding drivers to sockets */
typedef struct bind_req_t {
socket_t Socket;
u_char Function;
dev_info_t *dev_info;
} bind_req_t;
/* Flag to bind to all functions */
#define BIND_FN_ALL 0xff
typedef struct mtd_bind_t {
socket_t Socket;
u_int Attributes;
u_int CardOffset;
dev_info_t *dev_info;
} mtd_bind_t;
/* Events */
#define CS_EVENT_PRI_LOW 0
#define CS_EVENT_PRI_HIGH 1
#define CS_EVENT_WRITE_PROTECT 0x000001
#define CS_EVENT_CARD_LOCK 0x000002
#define CS_EVENT_CARD_INSERTION 0x000004
#define CS_EVENT_CARD_REMOVAL 0x000008
#define CS_EVENT_BATTERY_DEAD 0x000010
#define CS_EVENT_BATTERY_LOW 0x000020
#define CS_EVENT_READY_CHANGE 0x000040
#define CS_EVENT_CARD_DETECT 0x000080
#define CS_EVENT_RESET_REQUEST 0x000100
#define CS_EVENT_RESET_PHYSICAL 0x000200
#define CS_EVENT_CARD_RESET 0x000400
#define CS_EVENT_REGISTRATION_COMPLETE 0x000800
#define CS_EVENT_RESET_COMPLETE 0x001000
#define CS_EVENT_PM_SUSPEND 0x002000
#define CS_EVENT_PM_RESUME 0x004000
#define CS_EVENT_INSERTION_REQUEST 0x008000
#define CS_EVENT_EJECTION_REQUEST 0x010000
#define CS_EVENT_MTD_REQUEST 0x020000
#define CS_EVENT_ERASE_COMPLETE 0x040000
#define CS_EVENT_REQUEST_ATTENTION 0x080000
#define CS_EVENT_CB_DETECT 0x100000
#define CS_EVENT_3VCARD 0x200000
#define CS_EVENT_XVCARD 0x400000
/* Return codes */
#define CS_SUCCESS 0x00
#define CS_BAD_ADAPTER 0x01
#define CS_BAD_ATTRIBUTE 0x02
#define CS_BAD_BASE 0x03
#define CS_BAD_EDC 0x04
#define CS_BAD_IRQ 0x06
#define CS_BAD_OFFSET 0x07
#define CS_BAD_PAGE 0x08
#define CS_READ_FAILURE 0x09
#define CS_BAD_SIZE 0x0a
#define CS_BAD_SOCKET 0x0b
#define CS_BAD_TYPE 0x0d
#define CS_BAD_VCC 0x0e
#define CS_BAD_VPP 0x0f
#define CS_BAD_WINDOW 0x11
#define CS_WRITE_FAILURE 0x12
#define CS_NO_CARD 0x14
#define CS_UNSUPPORTED_FUNCTION 0x15
#define CS_UNSUPPORTED_MODE 0x16
#define CS_BAD_SPEED 0x17
#define CS_BUSY 0x18
#define CS_GENERAL_FAILURE 0x19
#define CS_WRITE_PROTECTED 0x1a
#define CS_BAD_ARG_LENGTH 0x1b
#define CS_BAD_ARGS 0x1c
#define CS_CONFIGURATION_LOCKED 0x1d
#define CS_IN_USE 0x1e
#define CS_NO_MORE_ITEMS 0x1f
#define CS_OUT_OF_RESOURCE 0x20
#define CS_BAD_HANDLE 0x21
#define CS_BAD_TUPLE 0x40
#ifdef __KERNEL__
/*
* Calls to set up low-level "Socket Services" drivers
*/
typedef int (*ss_entry_t)(u_int sock, u_int cmd, void *arg);
extern int register_ss_entry(int nsock, ss_entry_t entry);
extern void unregister_ss_entry(ss_entry_t entry);
/*
* The main Card Services entry point
*/
enum service {
AccessConfigurationRegister, AddSocketServices,
AdjustResourceInfo, CheckEraseQueue, CloseMemory, CopyMemory,
DeregisterClient, DeregisterEraseQueue, GetCardServicesInfo,
GetClientInfo, GetConfigurationInfo, GetEventMask,
GetFirstClient, GetFirstPartion, GetFirstRegion, GetFirstTuple,
GetNextClient, GetNextPartition, GetNextRegion, GetNextTuple,
GetStatus, GetTupleData, MapLogSocket, MapLogWindow, MapMemPage,
MapPhySocket, MapPhyWindow, ModifyConfiguration, ModifyWindow,
OpenMemory, ParseTuple, ReadMemory, RegisterClient,
RegisterEraseQueue, RegisterMTD, RegisterTimer,
ReleaseConfiguration, ReleaseExclusive, ReleaseIO, ReleaseIRQ,
ReleaseSocketMask, ReleaseWindow, ReplaceSocketServices,
RequestConfiguration, RequestExclusive, RequestIO, RequestIRQ,
RequestSocketMask, RequestWindow, ResetCard, ReturnSSEntry,
SetEventMask, SetRegion, ValidateCIS, VendorSpecific,
WriteMemory, BindDevice, BindMTD, ReportError,
SuspendCard, ResumeCard, EjectCard, InsertCard, ReplaceCIS,
GetFirstWindow, GetNextWindow, GetMemPage
};
#ifdef IN_CARD_SERVICES
extern int CardServices(int func, void *a1, void *a2, void *a3);
#else
extern int CardServices(int func, ...);
#endif
#endif /* __KERNEL__ */
#endif /* _LINUX_CS_H */

70
pcmcia/cs_types.h Normal file
View File

@ -0,0 +1,70 @@
/*
* cs_types.h 1.20 2002/04/17 02:52:39
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#ifndef _LINUX_CS_TYPES_H
#define _LINUX_CS_TYPES_H
#ifdef __linux__
#ifdef __KERNEL__
#include <linux/types.h>
#else
#include <sys/types.h>
#endif
#endif
#ifdef __arm__
typedef u_int ioaddr_t;
#else
typedef u_short ioaddr_t;
#endif
typedef u_short socket_t;
typedef u_int event_t;
typedef u_char cisdata_t;
typedef u_short page_t;
struct client_t;
typedef struct client_t *client_handle_t;
struct window_t;
typedef struct window_t *window_handle_t;
struct region_t;
typedef struct region_t *memory_handle_t;
struct eraseq_t;
typedef struct eraseq_t *eraseq_handle_t;
#ifndef DEV_NAME_LEN
#define DEV_NAME_LEN 32
#endif
typedef char dev_info_t[DEV_NAME_LEN];
#endif /* _LINUX_CS_TYPES_H */

73
pcmcia/driver_ops.h Normal file
View File

@ -0,0 +1,73 @@
/*
* driver_ops.h 1.17 2001/10/04 03:15:22
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#ifndef _LINUX_DRIVER_OPS_H
#define _LINUX_DRIVER_OPS_H
#ifndef DEV_NAME_LEN
#define DEV_NAME_LEN 32
#endif
#ifdef __KERNEL__
typedef struct dev_node_t {
char dev_name[DEV_NAME_LEN];
u_short major, minor;
struct dev_node_t *next;
} dev_node_t;
typedef struct dev_locator_t {
enum { LOC_ISA, LOC_PCI } bus;
union {
struct {
u_short io_base_1, io_base_2;
u_long mem_base;
u_char irq, dma;
} isa;
struct {
u_char bus;
u_char devfn;
} pci;
} b;
} dev_locator_t;
typedef struct driver_operations {
char *name;
dev_node_t *(*attach) (dev_locator_t *loc);
void (*suspend) (dev_node_t *dev);
void (*resume) (dev_node_t *dev);
void (*detach) (dev_node_t *dev);
} driver_operations;
int register_driver(struct driver_operations *ops);
void unregister_driver(struct driver_operations *ops);
#endif /* __KERNEL__ */
#endif /* _LINUX_DRIVER_OPS_H */

148
pcmcia/ds.h Normal file
View File

@ -0,0 +1,148 @@
/*
* ds.h 1.58 2001/10/04 03:15:22
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#ifndef _LINUX_DS_H
#define _LINUX_DS_H
#include <pcmcia/driver_ops.h>
#include <pcmcia/bulkmem.h>
typedef struct tuple_parse_t {
tuple_t tuple;
cisdata_t data[255];
cisparse_t parse;
} tuple_parse_t;
typedef struct win_info_t {
window_handle_t handle;
win_req_t window;
memreq_t map;
} win_info_t;
typedef struct bind_info_t {
dev_info_t dev_info;
u_char function;
struct dev_link_t *instance;
char name[DEV_NAME_LEN];
u_short major, minor;
void *next;
} bind_info_t;
typedef struct mtd_info_t {
dev_info_t dev_info;
u_int Attributes;
u_int CardOffset;
} mtd_info_t;
typedef union ds_ioctl_arg_t {
servinfo_t servinfo;
adjust_t adjust;
config_info_t config;
tuple_t tuple;
tuple_parse_t tuple_parse;
client_req_t client_req;
cs_status_t status;
conf_reg_t conf_reg;
cisinfo_t cisinfo;
region_info_t region;
bind_info_t bind_info;
mtd_info_t mtd_info;
win_info_t win_info;
cisdump_t cisdump;
} ds_ioctl_arg_t;
#define DS_GET_CARD_SERVICES_INFO _IOR ('d', 1, servinfo_t)
#define DS_ADJUST_RESOURCE_INFO _IOWR('d', 2, adjust_t)
#define DS_GET_CONFIGURATION_INFO _IOWR('d', 3, config_info_t)
#define DS_GET_FIRST_TUPLE _IOWR('d', 4, tuple_t)
#define DS_GET_NEXT_TUPLE _IOWR('d', 5, tuple_t)
#define DS_GET_TUPLE_DATA _IOWR('d', 6, tuple_parse_t)
#define DS_PARSE_TUPLE _IOWR('d', 7, tuple_parse_t)
#define DS_RESET_CARD _IO ('d', 8)
#define DS_GET_STATUS _IOWR('d', 9, cs_status_t)
#define DS_ACCESS_CONFIGURATION_REGISTER _IOWR('d', 10, conf_reg_t)
#define DS_VALIDATE_CIS _IOR ('d', 11, cisinfo_t)
#define DS_SUSPEND_CARD _IO ('d', 12)
#define DS_RESUME_CARD _IO ('d', 13)
#define DS_EJECT_CARD _IO ('d', 14)
#define DS_INSERT_CARD _IO ('d', 15)
#define DS_GET_FIRST_REGION _IOWR('d', 16, region_info_t)
#define DS_GET_NEXT_REGION _IOWR('d', 17, region_info_t)
#define DS_REPLACE_CIS _IOWR('d', 18, cisdump_t)
#define DS_GET_FIRST_WINDOW _IOR ('d', 19, win_info_t)
#define DS_GET_NEXT_WINDOW _IOWR('d', 20, win_info_t)
#define DS_GET_MEM_PAGE _IOWR('d', 21, win_info_t)
#define DS_BIND_REQUEST _IOWR('d', 60, bind_info_t)
#define DS_GET_DEVICE_INFO _IOWR('d', 61, bind_info_t)
#define DS_GET_NEXT_DEVICE _IOWR('d', 62, bind_info_t)
#define DS_UNBIND_REQUEST _IOW ('d', 63, bind_info_t)
#define DS_BIND_MTD _IOWR('d', 64, mtd_info_t)
#ifdef __KERNEL__
typedef struct dev_link_t {
dev_node_t *dev;
u_int state, open;
wait_queue_head_t pending;
struct timer_list release;
client_handle_t handle;
io_req_t io;
irq_req_t irq;
config_req_t conf;
window_handle_t win;
void *priv;
struct dev_link_t *next;
} dev_link_t;
/* Flags for device state */
#define DEV_PRESENT 0x01
#define DEV_CONFIG 0x02
#define DEV_STALE_CONFIG 0x04 /* release on close */
#define DEV_STALE_LINK 0x08 /* detach on release */
#define DEV_CONFIG_PENDING 0x10
#define DEV_RELEASE_PENDING 0x20
#define DEV_SUSPEND 0x40
#define DEV_BUSY 0x80
#define DEV_OK(l) \
((l) && ((l->state & ~DEV_BUSY) == (DEV_CONFIG|DEV_PRESENT)))
int register_pccard_driver(dev_info_t *dev_info,
dev_link_t *(*attach)(void),
void (*detach)(dev_link_t *));
int unregister_pccard_driver(dev_info_t *dev_info);
#define register_pcmcia_driver register_pccard_driver
#define unregister_pcmcia_driver unregister_pccard_driver
#endif /* __KERNEL__ */
#endif /* _LINUX_DS_H */

154
pcmcia/i82365.h Normal file
View File

@ -0,0 +1,154 @@
/*
* i82365.h 1.20 2000/07/20 23:00:27
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License version 2 (the "GPL"), in which
* case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#ifndef _LINUX_I82365_H
#define _LINUX_I82365_H
/* register definitions for the Intel 82365SL PCMCIA controller */
/* Offsets for PCIC registers */
#define I365_IDENT 0x00 /* Identification and revision */
#define I365_STATUS 0x01 /* Interface status */
#define I365_POWER 0x02 /* Power and RESETDRV control */
#define I365_INTCTL 0x03 /* Interrupt and general control */
#define I365_CSC 0x04 /* Card status change */
#define I365_CSCINT 0x05 /* Card status change interrupt control */
#define I365_ADDRWIN 0x06 /* Address window enable */
#define I365_IOCTL 0x07 /* I/O control */
#define I365_GENCTL 0x16 /* Card detect and general control */
#define I365_GBLCTL 0x1E /* Global control register */
/* Offsets for I/O and memory window registers */
#define I365_IO(map) (0x08+((map)<<2))
#define I365_MEM(map) (0x10+((map)<<3))
#define I365_W_START 0
#define I365_W_STOP 2
#define I365_W_OFF 4
/* Flags for I365_STATUS */
#define I365_CS_BVD1 0x01
#define I365_CS_STSCHG 0x01
#define I365_CS_BVD2 0x02
#define I365_CS_SPKR 0x02
#define I365_CS_DETECT 0x0C
#define I365_CS_WRPROT 0x10
#define I365_CS_READY 0x20 /* Inverted */
#define I365_CS_POWERON 0x40
#define I365_CS_GPI 0x80
/* Flags for I365_POWER */
#define I365_PWR_OFF 0x00 /* Turn off the socket */
#define I365_PWR_OUT 0x80 /* Output enable */
#define I365_PWR_NORESET 0x40 /* Disable RESETDRV on resume */
#define I365_PWR_AUTO 0x20 /* Auto pwr switch enable */
#define I365_VCC_MASK 0x18 /* Mask for turning off Vcc */
/* There are different layouts for B-step and DF-step chips: the B
step has independent Vpp1/Vpp2 control, and the DF step has only
Vpp1 control, plus 3V control */
#define I365_VCC_5V 0x10 /* Vcc = 5.0v */
#define I365_VCC_3V 0x18 /* Vcc = 3.3v */
#define I365_VPP2_MASK 0x0c /* Mask for turning off Vpp2 */
#define I365_VPP2_5V 0x04 /* Vpp2 = 5.0v */
#define I365_VPP2_12V 0x08 /* Vpp2 = 12.0v */
#define I365_VPP1_MASK 0x03 /* Mask for turning off Vpp1 */
#define I365_VPP1_5V 0x01 /* Vpp2 = 5.0v */
#define I365_VPP1_12V 0x02 /* Vpp2 = 12.0v */
/* Flags for I365_INTCTL */
#define I365_RING_ENA 0x80
#define I365_PC_RESET 0x40
#define I365_PC_IOCARD 0x20
#define I365_INTR_ENA 0x10
#define I365_IRQ_MASK 0x0F
/* Flags for I365_CSC and I365_CSCINT*/
#define I365_CSC_BVD1 0x01
#define I365_CSC_STSCHG 0x01
#define I365_CSC_BVD2 0x02
#define I365_CSC_READY 0x04
#define I365_CSC_DETECT 0x08
#define I365_CSC_ANY 0x0F
#define I365_CSC_GPI 0x10
/* Flags for I365_ADDRWIN */
#define I365_ADDR_MEMCS16 0x20
#define I365_ENA_IO(map) (0x40 << (map))
#define I365_ENA_MEM(map) (0x01 << (map))
/* Flags for I365_IOCTL */
#define I365_IOCTL_MASK(map) (0x0F << (map<<2))
#define I365_IOCTL_WAIT(map) (0x08 << (map<<2))
#define I365_IOCTL_0WS(map) (0x04 << (map<<2))
#define I365_IOCTL_IOCS16(map) (0x02 << (map<<2))
#define I365_IOCTL_16BIT(map) (0x01 << (map<<2))
/* Flags for I365_GENCTL */
#define I365_CTL_16DELAY 0x01
#define I365_CTL_RESET 0x02
#define I365_CTL_GPI_ENA 0x04
#define I365_CTL_GPI_CTL 0x08
#define I365_CTL_RESUME 0x10
#define I365_CTL_SW_IRQ 0x20
/* Flags for I365_GBLCTL */
#define I365_GBL_PWRDOWN 0x01
#define I365_GBL_CSC_LEV 0x02
#define I365_GBL_WRBACK 0x04
#define I365_GBL_IRQ_0_LEV 0x08
#define I365_GBL_IRQ_1_LEV 0x10
/* Flags for memory window registers */
#define I365_MEM_16BIT 0x8000 /* In memory start high byte */
#define I365_MEM_0WS 0x4000
#define I365_MEM_WS1 0x8000 /* In memory stop high byte */
#define I365_MEM_WS0 0x4000
#define I365_MEM_WRPROT 0x8000 /* In offset high byte */
#define I365_MEM_REG 0x4000
#define I365_REG(slot, reg) (((slot) << 6) | (reg))
/* Default ISA interrupt mask */
#define I365_ISA_IRQ_MASK 0xdeb8 /* irq's 3-5,7,9-12,14,15 */
/* Device ID's for PCI-to-PCMCIA bridges */
#ifndef PCI_VENDOR_ID_INTEL
#define PCI_VENDOR_ID_INTEL 0x8086
#endif
#ifndef PCI_DEVICE_ID_INTEL_82092AA_0
#define PCI_DEVICE_ID_INTEL_82092AA_0 0x1221
#endif
#ifndef PCI_VENDOR_ID_OMEGA
#define PCI_VENDOR_ID_OMEGA 0x119b
#endif
#ifndef PCI_DEVICE_ID_OMEGA_82C092G
#define PCI_DEVICE_ID_OMEGA_82C092G 0x1221
#endif
#endif /* _LINUX_I82365_H */

2062
pcmcia/lex_config.c Normal file

File diff suppressed because it is too large Load Diff

269
pcmcia/lex_config.l Normal file
View File

@ -0,0 +1,269 @@
/* Special state for handling include files */
%x src
%{
/*
* lex_config.l 1.49 2002/10/07 16:39:21
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#undef src
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#ifdef HAS_WORDEXP
#include <wordexp.h>
#else
#include <glob.h>
#endif
#define src 1
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include "yacc_config.h"
/* For assembling nice error messages */
char *current_file;
int current_lineno;
static int lex_number(char *s);
static int lex_string(char *s);
static void do_source(char *fn);
static int do_eof(void);
%}
int [0-9]+
hex 0x[0-9a-fA-F]+
str \"([^"]|\\.)*\"
%%
source[ \t]+ BEGIN(src); return SOURCE;
<src>[^\n]+ do_source(yytext); BEGIN(INITIAL);
<<EOF>> if (do_eof()) yyterminate();
\n current_lineno++;
[ \t]* /* skip */ ;
[ ]*[#;].* /* skip */ ;
anonymous return ANONYMOUS;
bind return BIND;
cis return CIS;
card return CARD;
class return CLASS;
default return DEFAULT;
device return DEVICE;
dtype return DTYPE;
exclude return EXCLUDE;
function return FUNCTION;
include return INCLUDE;
irq return IRQ_NO;
jedec return JEDEC;
manfid return MANFID;
memory return MEMORY;
module return MODULE;
mtd return MTD;
needs_mtd return NEEDS_MTD;
opts return OPTS;
pci return PCI;
port return PORT;
region return REGION;
reserve return RESERVE;
to return TO;
tuple return TUPLE;
version return VERSION;
memory_card return lex_number("1");
serial_port return lex_number("2");
parallel_port return lex_number("3");
fixed_disk return lex_number("4");
video_adapter return lex_number("5");
network_adapter return lex_number("6");
aims_card return lex_number("7");
scsi_adapter return lex_number("8");
{int} return lex_number(yytext);
{hex} return lex_number(yytext);
{str} return lex_string(yytext);
. return yytext[0];
%%
#ifndef yywrap
int yywrap() { return 1; }
#endif
/*======================================================================
Stuff to parse basic data types
======================================================================*/
static int lex_number(char *s)
{
yylval.num = strtoul(s, NULL, 0);
return NUMBER;
}
static int lex_string(char *s)
{
int n = strlen(s);
yylval.str = malloc(n-1);
strncpy(yylval.str, s+1, n-2);
yylval.str[n-2] = '\0';
return STRING;
}
/*======================================================================
Code to support nesting of configuration files
======================================================================*/
#define MAX_SOURCE_DEPTH 4
struct source_stack {
YY_BUFFER_STATE buffer;
char *filename;
int lineno, fileno;
FILE *file;
#ifdef HAS_WORDEXP
wordexp_t word;
#else
glob_t glob;
#endif
} source_stack[MAX_SOURCE_DEPTH];
static int source_stack_ptr = 0;
static int parse_env = 0;
static int get_glob(void)
{
struct source_stack *s = &source_stack[source_stack_ptr];
#ifdef HAS_WORDEXP
while (s->fileno < s->word.we_wordc) {
char *fn = s->word.we_wordv[s->fileno];
#else
while (s->fileno < s->glob.gl_pathc) {
char *fn = s->glob.gl_pathv[s->fileno];
#endif
s->file = fopen(fn, "r");
if (s->file == NULL) {
if (strpbrk(fn, "?*[") == NULL)
syslog(LOG_INFO, "could not open '%s': %m", fn);
s->fileno++;
} else {
current_lineno = 1;
current_file = strdup(fn);
yy_switch_to_buffer(yy_create_buffer(s->file, YY_BUF_SIZE));
source_stack_ptr++;
s->fileno++;
return 0;
}
}
return -1;
}
static void do_source(char *fn)
{
struct source_stack *s = &source_stack[source_stack_ptr];
if (source_stack_ptr >= MAX_SOURCE_DEPTH) {
syslog(LOG_INFO, "source depth limit exceeded");
return;
}
#ifdef HAS_WORDEXP
wordexp(fn, &s->word, 0);
#else
glob(fn, GLOB_NOCHECK, NULL, &s->glob);
#endif
s->fileno = 0;
s->buffer = YY_CURRENT_BUFFER;
s->lineno = current_lineno;
s->filename = current_file;
get_glob();
}
static int do_eof(void)
{
struct source_stack *s = &source_stack[--source_stack_ptr];
if (source_stack_ptr < 0) {
if (parse_env == 0) {
char *t = getenv("PCMCIA_OPTS");
if (t == NULL) return -1;
parse_env = 1;
source_stack_ptr = 0;
current_file = "PCMCIA_OPTS";
current_lineno = 1;
yy_scan_string(t);
return 0;
} else
return -1;
}
fclose(s->file);
free(current_file);
yy_delete_buffer(YY_CURRENT_BUFFER);
if (get_glob() != 0) {
yy_switch_to_buffer(s->buffer);
current_lineno = s->lineno;
current_file = s->filename;
}
return 0;
}
/*======================================================================
The main entry point... returns -1 if the file can't be accessed.
======================================================================*/
int parse_configfile(char *fn)
{
FILE *f;
f = fopen(fn, "r");
if (!f) {
syslog(LOG_INFO, "could not open '%s': %m", fn);
return -1;
}
current_lineno = 1;
current_file = fn;
source_stack_ptr = 0;
yyrestart(f);
yyparse();
fclose(f);
return 0;
}

21
pcmcia/pcmcia.h Normal file
View File

@ -0,0 +1,21 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
#ifndef _PCMCIA_CARDMGR_INTERFACE_H_
#define _PCMCIA_CARDMGR_INTERFACE_H_
char * pcmcia_probe(void);
int cardmgr_call(void);
#endif

419
pcmcia/pcmcia_probe.c Normal file
View File

@ -0,0 +1,419 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000-2001 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/* Code comes from /anonymous@projects.sourceforge.net:/pub/pcmcia-cs/pcmcia-cs-3.1.28.tar.bz2
*
* Licence of this code follows:
PCMCIA controller probe
probe.c 1.54 2001/05/10 03:01:59
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The initial developer of the original code is David A. Hinds
<dahinds@users.sourceforge.net>. Portions created by David A. Hinds
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
terms of the GNU Public License version 2 (the "GPL"), in which
case the provisions of the GPL are applicable instead of the
above. If you wish to allow the use of your version of this file
only under the terms of the GPL and not to allow others to use
your version of this file under the MPL, indicate your decision
by deleting the provisions above and replace them with the notice
and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this
file under either the MPL or the GPL.
======================================================================*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "log.h"
#include "pcmcia.h"
/*====================================================================*/
typedef struct {
u_short vendor, device;
char *tag;
char *name;
} pci_id_t;
pci_id_t pci_id[] = {
{ 0x1013, 0x1100, "Cirrus Logic CL 6729", "Cirrus PD6729" },
{ 0x1013, 0x1110, "Cirrus Logic PD 6832", "Cirrus PD6832" },
{ 0x10b3, 0xb106, "SMC 34C90", "SMC 34C90" },
{ 0x1180, 0x0465, "Ricoh RL5C465", "Ricoh RL5C465" },
{ 0x1180, 0x0466, "Ricoh RL5C466", "Ricoh RL5C466" },
{ 0x1180, 0x0475, "Ricoh RL5C475", "Ricoh RL5C475" },
{ 0x1180, 0x0476, "Ricoh RL5C476", "Ricoh RL5C476" },
{ 0x1180, 0x0478, "Ricoh RL5C478", "Ricoh RL5C478" },
{ 0x104c, 0xac12, "Texas Instruments PCI1130", "TI 1130" },
{ 0x104c, 0xac13, "Texas Instruments PCI1031", "TI 1031" },
{ 0x104c, 0xac15, "Texas Instruments PCI1131", "TI 1131" },
{ 0x104c, 0xac1a, "Texas Instruments PCI1210", "TI 1210" },
{ 0x104c, 0xac1e, "Texas Instruments PCI1211", "TI 1211" },
{ 0x104c, 0xac17, "Texas Instruments PCI1220", "TI 1220" },
{ 0x104c, 0xac19, "Texas Instruments PCI1221", "TI 1221" },
{ 0x104c, 0xac1c, "Texas Instruments PCI1225", "TI 1225" },
{ 0x104c, 0xac16, "Texas Instruments PCI1250", "TI 1250A" },
{ 0x104c, 0xac1d, "Texas Instruments PCI1251A", "TI 1251A" },
{ 0x104c, 0xac1f, "Texas Instruments PCI1251B", "TI 1251B" },
{ 0x104c, 0xac50, "Texas Instruments PCI1410", "TI 1410" },
{ 0x104c, 0xac51, "Texas Instruments PCI1420", "TI 1420" },
{ 0x104c, 0xac52, "Texas Instruments PCI1451", "TI 1451" },
{ 0x104c, 0xac53, "Texas Instruments PCI1421", "TI 1421" },
{ 0x104c, 0xac54, "Texas Instruments PCI1620", "TI 1620" },
{ 0x104c, 0xac55, "Texas Instruments PCI1250", "TI 1250" },
{ 0x104c, 0xac56, "Texas Instruments PCI1510", "TI 1510" },
{ 0x104c, 0xac57, "Texas Instruments PCI1530", "TI 1530" },
{ 0x104c, 0xac58, "Texas Instruments PCI1515", "TI 1515" },
{ 0x104c, 0xac59, "Texas Instruments PCI1621", "TI 1621" },
{ 0x104c, 0xac5a, "Texas Instruments PCI1610", "TI 1610" },
{ 0x104c, 0xac1b, "Texas Instruments PCI1450", "TI 1450" },
{ 0x104c, 0xac52, "Texas Instruments PCI1451", "TI 1451" },
{ 0x104c, 0xac41, "Texas Instruments PCI4410", "TI 4410" },
{ 0x104c, 0xac40, "Texas Instruments PCI4450", "TI 4450" },
{ 0x104c, 0xac42, "Texas Instruments PCI4451", "TI 4451" },
{ 0x1217, 0x6729, "O2 Micro 6729", "O2Micro OZ6729" },
{ 0x1217, 0x673a, "O2 Micro 6730", "O2Micro OZ6730" },
{ 0x1217, 0x6832, "O2 Micro 6832/6833", "O2Micro OZ6832/OZ6833" },
{ 0x1217, 0x6836, "O2 Micro 6836/6860", "O2Micro OZ6836/OZ6860" },
{ 0x1217, 0x6872, "O2 Micro 6812", "O2Micro OZ6812" },
{ 0x1179, 0x0603, "Toshiba ToPIC95-A", "Toshiba ToPIC95-A" },
{ 0x1179, 0x060a, "Toshiba ToPIC95-B", "Toshiba ToPIC95-B" },
{ 0x1179, 0x060f, "Toshiba ToPIC97", "Toshiba ToPIC97" },
{ 0x1179, 0x0617, "Toshiba ToPIC100", "Toshiba ToPIC100" },
{ 0x119b, 0x1221, "Omega Micro 82C092G", "Omega Micro 82C092G" },
{ 0x1524, 0x1211, "ENE Technology Inc|CB1211 Cardbus Controller", "ENE CB1211" },
{ 0x1524, 0x1225, "ENE Technology Inc|CB1225 Cardbus Controller", "ENE CB1225" },
{ 0x1524, 0x1410, "ENE Technology Inc|CB1410 Cardbus Controller", "ENE CB1410" },
{ 0x1524, 0x1420, "ENE Technology Inc|CB1420 Cardbus Controller", "ENE CB1420" },
{ 0x8086, 0x1221, "Intel 82092AA", "Intel 82092AA" }
};
#define PCI_COUNT (sizeof(pci_id)/sizeof(pci_id_t))
static int pci_probe(void)
{
char s[256], *name = NULL;
u_int device, vendor, i;
FILE *f;
log_message("PCMCIA: probing PCI bus..");
f = fopen("/proc/bus/pci/devices", "r");
if (!f) {
log_message("where are you going without /proc/bus/pci/devices ??");
return -1;
}
while (fgets(s, 256, f) != NULL) {
u_int n = strtoul(s+5, NULL, 16);
vendor = (n >> 16); device = (n & 0xffff);
for (i = 0; i < PCI_COUNT; i++)
if ((vendor == pci_id[i].vendor) &&
(device == pci_id[i].device)) break;
if (i < PCI_COUNT) {
name = pci_id[i].name;
break;
}
}
fclose(f);
if (name) {
log_message("\t%s found, 2 sockets.", name);
return 0;
} else {
log_message("\tnot found.");
return -ENODEV;
}
}
/*====================================================================*/
#include <sys/io.h>
typedef u_short ioaddr_t;
#include "i82365.h"
#include "cirrus.h"
#include "vg468.h"
static ioaddr_t i365_base = 0x03e0;
static u_char i365_get(u_short sock, u_short reg)
{
u_char val = I365_REG(sock, reg);
outb(val, i365_base); val = inb(i365_base+1);
return val;
}
static void i365_set(u_short sock, u_short reg, u_char data)
{
u_char val = I365_REG(sock, reg);
outb(val, i365_base); outb(data, i365_base+1);
}
static void i365_bset(u_short sock, u_short reg, u_char mask)
{
u_char d = i365_get(sock, reg);
d |= mask;
i365_set(sock, reg, d);
}
static void i365_bclr(u_short sock, u_short reg, u_char mask)
{
u_char d = i365_get(sock, reg);
d &= ~mask;
i365_set(sock, reg, d);
}
static int i365_probe(void)
{
int val, sock, done;
char *name = "i82365sl";
log_message("PCMCIA: probing for Intel PCIC (ISA)..");
sock = done = 0;
if (ioperm(i365_base, 4, 1)) {
log_perror("PCMCIA: ioperm");
return -1;
}
ioperm(0x80, 1, 1);
for (; sock < 2; sock++) {
val = i365_get(sock, I365_IDENT);
switch (val) {
case 0x82:
name = "i82365sl A step";
break;
case 0x83:
name = "i82365sl B step";
break;
case 0x84:
name = "VLSI 82C146";
break;
case 0x88: case 0x89: case 0x8a:
name = "IBM Clone";
break;
case 0x8b: case 0x8c:
break;
default:
done = 1;
}
if (done) break;
}
if (sock == 0) {
log_message("\tnot found.");
return -ENODEV;
}
if ((sock == 2) && (strcmp(name, "VLSI 82C146") == 0))
name = "i82365sl DF";
/* Check for Vadem chips */
outb(0x0e, i365_base);
outb(0x37, i365_base);
i365_bset(0, VG468_MISC, VG468_MISC_VADEMREV);
val = i365_get(0, I365_IDENT);
if (val & I365_IDENT_VADEM) {
if ((val & 7) < 4)
name = "Vadem VG-468";
else
name = "Vadem VG-469";
i365_bclr(0, VG468_MISC, VG468_MISC_VADEMREV);
}
/* Check for Cirrus CL-PD67xx chips */
i365_set(0, PD67_CHIP_INFO, 0);
val = i365_get(0, PD67_CHIP_INFO);
if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) {
val = i365_get(0, PD67_CHIP_INFO);
if ((val & PD67_INFO_CHIP_ID) == 0) {
if (val & PD67_INFO_SLOTS)
name = "Cirrus CL-PD672x";
else {
name = "Cirrus CL-PD6710";
sock = 1;
}
i365_set(0, PD67_EXT_INDEX, 0xe5);
if (i365_get(0, PD67_EXT_INDEX) != 0xe5)
name = "VIA VT83C469";
}
}
log_message("\t%s found, %d sockets.", name, sock);
return 0;
} /* i365_probe */
/*====================================================================*/
#include "tcic.h"
static u_char tcic_getb(ioaddr_t base, u_char reg)
{
u_char val = inb(base+reg);
return val;
}
static void tcic_setb(ioaddr_t base, u_char reg, u_char data)
{
outb(data, base+reg);
}
static u_short tcic_getw(ioaddr_t base, u_char reg)
{
u_short val = inw(base+reg);
return val;
}
static void tcic_setw(ioaddr_t base, u_char reg, u_short data)
{
outw(data, base+reg);
}
static u_short tcic_aux_getw(ioaddr_t base, u_short reg)
{
u_char mode = (tcic_getb(base, TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
tcic_setb(base, TCIC_MODE, mode);
return tcic_getw(base, TCIC_AUX);
}
static void tcic_aux_setw(ioaddr_t base, u_short reg, u_short data)
{
u_char mode = (tcic_getb(base, TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
tcic_setb(base, TCIC_MODE, mode);
tcic_setw(base, TCIC_AUX, data);
}
static int get_tcic_id(ioaddr_t base)
{
u_short id;
tcic_aux_setw(base, TCIC_AUX_TEST, TCIC_TEST_DIAG);
id = tcic_aux_getw(base, TCIC_AUX_ILOCK);
id = (id & TCIC_ILOCKTEST_ID_MASK) >> TCIC_ILOCKTEST_ID_SH;
tcic_aux_setw(base, TCIC_AUX_TEST, 0);
return id;
}
static int tcic_probe_at(ioaddr_t base)
{
int i;
u_short old;
/* Anything there?? */
for (i = 0; i < 0x10; i += 2)
if (tcic_getw(base, i) == 0xffff)
return -1;
log_message("\tat %#3.3x: ", base);
/* Try to reset the chip */
tcic_setw(base, TCIC_SCTRL, TCIC_SCTRL_RESET);
tcic_setw(base, TCIC_SCTRL, 0);
/* Can we set the addr register? */
old = tcic_getw(base, TCIC_ADDR);
tcic_setw(base, TCIC_ADDR, 0);
if (tcic_getw(base, TCIC_ADDR) != 0) {
tcic_setw(base, TCIC_ADDR, old);
return -2;
}
tcic_setw(base, TCIC_ADDR, 0xc3a5);
if (tcic_getw(base, TCIC_ADDR) != 0xc3a5)
return -3;
return 2;
}
static int tcic_probe(void)
{
int sock, id;
log_message("PCMCIA: probing for Databook TCIC-2 (ISA)..");
if (ioperm(TCIC_BASE, 16, 1)) {
log_perror("PCMCIA: ioperm");
return -1;
}
ioperm(0x80, 1, 1);
sock = tcic_probe_at(TCIC_BASE);
if (sock <= 0) {
log_message("\tnot found.");
return -ENODEV;
}
id = get_tcic_id(TCIC_BASE);
switch (id) {
case TCIC_ID_DB86082:
log_message("DB86082"); break;
case TCIC_ID_DB86082A:
log_message("DB86082A"); break;
case TCIC_ID_DB86084:
log_message("DB86084"); break;
case TCIC_ID_DB86084A:
log_message("DB86084A"); break;
case TCIC_ID_DB86072:
log_message("DB86072"); break;
case TCIC_ID_DB86184:
log_message("DB86184"); break;
case TCIC_ID_DB86082B:
log_message("DB86082B"); break;
default:
log_message("Unknown TCIC-2 ID 0x%02x", id);
}
log_message("\tfound at %#6x, %d sockets.\n", TCIC_BASE, sock);
return 0;
} /* tcic_probe */
/*====================================================================*/
char * pcmcia_probe(void)
{
if (!pci_probe())
return "yenta_socket";
else if (!i365_probe())
return "i82365";
else if (!tcic_probe())
return "tcic";
else
return NULL;
}

266
pcmcia/tcic.h Normal file
View File

@ -0,0 +1,266 @@
/*
* tcic.h 1.14 2000/06/12 21:29:37
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License version 2 (the "GPL"), in which
* case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#ifndef _LINUX_TCIC_H
#define _LINUX_TCIC_H
#define TCIC_BASE 0x240
/* offsets of registers from TCIC_BASE */
#define TCIC_DATA 0x00
#define TCIC_ADDR 0x02
#define TCIC_SCTRL 0x06
#define TCIC_SSTAT 0x07
#define TCIC_MODE 0x08
#define TCIC_PWR 0x09
#define TCIC_EDC 0x0A
#define TCIC_ICSR 0x0C
#define TCIC_IENA 0x0D
#define TCIC_AUX 0x0E
#define TCIC_SS_SHFT 12
#define TCIC_SS_MASK 0x7000
/* Flags for TCIC_ADDR */
#define TCIC_ADR2_REG 0x8000
#define TCIC_ADR2_INDREG 0x0800
#define TCIC_ADDR_REG 0x80000000
#define TCIC_ADDR_SS_SHFT (TCIC_SS_SHFT+16)
#define TCIC_ADDR_SS_MASK (TCIC_SS_MASK<<16)
#define TCIC_ADDR_INDREG 0x08000000
#define TCIC_ADDR_IO 0x04000000
#define TCIC_ADDR_MASK 0x03ffffff
/* Flags for TCIC_SCTRL */
#define TCIC_SCTRL_ENA 0x01
#define TCIC_SCTRL_INCMODE 0x18
#define TCIC_SCTRL_INCMODE_HOLD 0x00
#define TCIC_SCTRL_INCMODE_WORD 0x08
#define TCIC_SCTRL_INCMODE_REG 0x10
#define TCIC_SCTRL_INCMODE_AUTO 0x18
#define TCIC_SCTRL_EDCSUM 0x20
#define TCIC_SCTRL_RESET 0x80
/* Flags for TCIC_SSTAT */
#define TCIC_SSTAT_6US 0x01
#define TCIC_SSTAT_10US 0x02
#define TCIC_SSTAT_PROGTIME 0x04
#define TCIC_SSTAT_LBAT1 0x08
#define TCIC_SSTAT_LBAT2 0x10
#define TCIC_SSTAT_RDY 0x20 /* Inverted */
#define TCIC_SSTAT_WP 0x40
#define TCIC_SSTAT_CD 0x80 /* Card detect */
/* Flags for TCIC_MODE */
#define TCIC_MODE_PGMMASK 0x1f
#define TCIC_MODE_NORMAL 0x00
#define TCIC_MODE_PGMWR 0x01
#define TCIC_MODE_PGMRD 0x02
#define TCIC_MODE_PGMCE 0x04
#define TCIC_MODE_PGMDBW 0x08
#define TCIC_MODE_PGMWORD 0x10
#define TCIC_MODE_AUXSEL_MASK 0xe0
/* Registers accessed through TCIC_AUX, by setting TCIC_MODE */
#define TCIC_AUX_TCTL (0<<5)
#define TCIC_AUX_PCTL (1<<5)
#define TCIC_AUX_WCTL (2<<5)
#define TCIC_AUX_EXTERN (3<<5)
#define TCIC_AUX_PDATA (4<<5)
#define TCIC_AUX_SYSCFG (5<<5)
#define TCIC_AUX_ILOCK (6<<5)
#define TCIC_AUX_TEST (7<<5)
/* Flags for TCIC_PWR */
#define TCIC_PWR_VCC(sock) (0x01<<(sock))
#define TCIC_PWR_VCC_MASK 0x03
#define TCIC_PWR_VPP(sock) (0x08<<(sock))
#define TCIC_PWR_VPP_MASK 0x18
#define TCIC_PWR_CLIMENA 0x40
#define TCIC_PWR_CLIMSTAT 0x80
/* Flags for TCIC_ICSR */
#define TCIC_ICSR_CLEAR 0x01
#define TCIC_ICSR_SET 0x02
#define TCIC_ICSR_JAM (TCIC_ICSR_CLEAR|TCIC_ICSR_SET)
#define TCIC_ICSR_STOPCPU 0x04
#define TCIC_ICSR_ILOCK 0x08
#define TCIC_ICSR_PROGTIME 0x10
#define TCIC_ICSR_ERR 0x20
#define TCIC_ICSR_CDCHG 0x40
#define TCIC_ICSR_IOCHK 0x80
/* Flags for TCIC_IENA */
#define TCIC_IENA_CFG_MASK 0x03
#define TCIC_IENA_CFG_OFF 0x00 /* disabled */
#define TCIC_IENA_CFG_OD 0x01 /* active low, open drain */
#define TCIC_IENA_CFG_LOW 0x02 /* active low, totem pole */
#define TCIC_IENA_CFG_HIGH 0x03 /* active high, totem pole */
#define TCIC_IENA_ILOCK 0x08
#define TCIC_IENA_PROGTIME 0x10
#define TCIC_IENA_ERR 0x20 /* overcurrent or iochk */
#define TCIC_IENA_CDCHG 0x40
/* Flags for TCIC_AUX_WCTL */
#define TCIC_WAIT_COUNT_MASK 0x001f
#define TCIC_WAIT_ASYNC 0x0020
#define TCIC_WAIT_SENSE 0x0040
#define TCIC_WAIT_SRC 0x0080
#define TCIC_WCTL_WR 0x0100
#define TCIC_WCTL_RD 0x0200
#define TCIC_WCTL_CE 0x0400
#define TCIC_WCTL_LLBAT1 0x0800
#define TCIC_WCTL_LLBAT2 0x1000
#define TCIC_WCTL_LRDY 0x2000
#define TCIC_WCTL_LWP 0x4000
#define TCIC_WCTL_LCD 0x8000
/* Flags for TCIC_AUX_SYSCFG */
#define TCIC_SYSCFG_IRQ_MASK 0x000f
#define TCIC_SYSCFG_MCSFULL 0x0010
#define TCIC_SYSCFG_IO1723 0x0020
#define TCIC_SYSCFG_MCSXB 0x0040
#define TCIC_SYSCFG_ICSXB 0x0080
#define TCIC_SYSCFG_NOPDN 0x0100
#define TCIC_SYSCFG_MPSEL_SHFT 9
#define TCIC_SYSCFG_MPSEL_MASK 0x0e00
#define TCIC_SYSCFG_MPSENSE 0x2000
#define TCIC_SYSCFG_AUTOBUSY 0x4000
#define TCIC_SYSCFG_ACC 0x8000
#define TCIC_ILOCK_OUT 0x01
#define TCIC_ILOCK_SENSE 0x02
#define TCIC_ILOCK_CRESET 0x04
#define TCIC_ILOCK_CRESENA 0x08
#define TCIC_ILOCK_CWAIT 0x10
#define TCIC_ILOCK_CWAITSNS 0x20
#define TCIC_ILOCK_HOLD_MASK 0xc0
#define TCIC_ILOCK_HOLD_CCLK 0xc0
#define TCIC_ILOCKTEST_ID_SH 8
#define TCIC_ILOCKTEST_ID_MASK 0x7f00
#define TCIC_ILOCKTEST_MCIC_1 0x8000
#define TCIC_ID_DB86082 0x02
#define TCIC_ID_DB86082A 0x03
#define TCIC_ID_DB86084 0x04
#define TCIC_ID_DB86084A 0x08
#define TCIC_ID_DB86072 0x15
#define TCIC_ID_DB86184 0x14
#define TCIC_ID_DB86082B 0x17
#define TCIC_TEST_DIAG 0x8000
/*
* Indirectly addressed registers
*/
#define TCIC_SCF1(sock) ((sock)<<3)
#define TCIC_SCF2(sock) (((sock)<<3)+2)
/* Flags for SCF1 */
#define TCIC_SCF1_IRQ_MASK 0x000f
#define TCIC_SCF1_IRQ_OFF 0x0000
#define TCIC_SCF1_IRQOC 0x0010
#define TCIC_SCF1_PCVT 0x0020
#define TCIC_SCF1_IRDY 0x0040
#define TCIC_SCF1_ATA 0x0080
#define TCIC_SCF1_DMA_SHIFT 8
#define TCIC_SCF1_DMA_MASK 0x0700
#define TCIC_SCF1_DMA_OFF 0
#define TCIC_SCF1_DREQ2 2
#define TCIC_SCF1_IOSTS 0x0800
#define TCIC_SCF1_SPKR 0x1000
#define TCIC_SCF1_FINPACK 0x2000
#define TCIC_SCF1_DELWR 0x4000
#define TCIC_SCF1_HD7IDE 0x8000
/* Flags for SCF2 */
#define TCIC_SCF2_RI 0x0001
#define TCIC_SCF2_IDBR 0x0002
#define TCIC_SCF2_MDBR 0x0004
#define TCIC_SCF2_MLBAT1 0x0008
#define TCIC_SCF2_MLBAT2 0x0010
#define TCIC_SCF2_MRDY 0x0020
#define TCIC_SCF2_MWP 0x0040
#define TCIC_SCF2_MCD 0x0080
#define TCIC_SCF2_MALL 0x00f8
/* Indirect addresses for memory window registers */
#define TCIC_MWIN(sock,map) (0x100+(((map)+((sock)<<2))<<3))
#define TCIC_MBASE_X 2
#define TCIC_MMAP_X 4
#define TCIC_MCTL_X 6
#define TCIC_MBASE_4K_BIT 0x4000
#define TCIC_MBASE_HA_SHFT 12
#define TCIC_MBASE_HA_MASK 0x0fff
#define TCIC_MMAP_REG 0x8000
#define TCIC_MMAP_CA_SHFT 12
#define TCIC_MMAP_CA_MASK 0x3fff
#define TCIC_MCTL_WSCNT_MASK 0x001f
#define TCIC_MCTL_WCLK 0x0020
#define TCIC_MCTL_WCLK_CCLK 0x0000
#define TCIC_MCTL_WCLK_BCLK 0x0020
#define TCIC_MCTL_QUIET 0x0040
#define TCIC_MCTL_WP 0x0080
#define TCIC_MCTL_ACC 0x0100
#define TCIC_MCTL_KE 0x0200
#define TCIC_MCTL_EDC 0x0400
#define TCIC_MCTL_B8 0x0800
#define TCIC_MCTL_SS_SHFT TCIC_SS_SHFT
#define TCIC_MCTL_SS_MASK TCIC_SS_MASK
#define TCIC_MCTL_ENA 0x8000
/* Indirect addresses for I/O window registers */
#define TCIC_IWIN(sock,map) (0x200+(((map)+((sock)<<1))<<2))
#define TCIC_IBASE_X 0
#define TCIC_ICTL_X 2
#define TCIC_ICTL_WSCNT_MASK TCIC_MCTL_WSCNT_MASK
#define TCIC_ICTL_QUIET TCIC_MCTL_QUIET
#define TCIC_ICTL_1K 0x0080
#define TCIC_ICTL_PASS16 0x0100
#define TCIC_ICTL_ACC TCIC_MCTL_ACC
#define TCIC_ICTL_TINY 0x0200
#define TCIC_ICTL_B16 0x0400
#define TCIC_ICTL_B8 TCIC_MCTL_B8
#define TCIC_ICTL_BW_MASK (TCIC_ICTL_B16|TCIC_ICTL_B8)
#define TCIC_ICTL_BW_DYN 0
#define TCIC_ICTL_BW_8 TCIC_ICTL_B8
#define TCIC_ICTL_BW_16 TCIC_ICTL_B16
#define TCIC_ICTL_BW_ATA (TCIC_ICTL_B16|TCIC_ICTL_B8)
#define TCIC_ICTL_SS_SHFT TCIC_SS_SHFT
#define TCIC_ICTL_SS_MASK TCIC_SS_MASK
#define TCIC_ICTL_ENA TCIC_MCTL_ENA
#endif /* _LINUX_TCIC_H */

13
pcmcia/version.h Normal file
View File

@ -0,0 +1,13 @@
/* version.h 1.114 2002/11/06 05:23:52 (David Hinds) */
#define CS_PKG_RELEASE "3.2.4"
#define CS_PKG_RELEASE_CODE 0x3204
#define VERSION(v,p,s) (((v)<<16)+(p<<8)+s)
#ifdef CONFIG_PCMCIA
#include_next <pcmcia/version.h>
#else
#define CS_RELEASE CS_PKG_RELEASE
#define CS_RELEASE_CODE CS_PKG_RELEASE_CODE
#endif

112
pcmcia/vg468.h Normal file
View File

@ -0,0 +1,112 @@
/*
* vg468.h 1.13 2000/06/12 21:29:37
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License version 2 (the "GPL"), in which
* case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#ifndef _LINUX_VG468_H
#define _LINUX_VG468_H
/* Special bit in I365_IDENT used for Vadem chip detection */
#define I365_IDENT_VADEM 0x08
/* Special definitions in I365_POWER */
#define VG468_VPP2_MASK 0x0c
#define VG468_VPP2_5V 0x04
#define VG468_VPP2_12V 0x08
/* Unique Vadem registers */
#define VG469_VSENSE 0x1f /* Card voltage sense */
#define VG469_VSELECT 0x2f /* Card voltage select */
#define VG468_CTL 0x38 /* Control register */
#define VG468_TIMER 0x39 /* Timer control */
#define VG468_MISC 0x3a /* Miscellaneous */
#define VG468_GPIO_CFG 0x3b /* GPIO configuration */
#define VG469_EXT_MODE 0x3c /* Extended mode register */
#define VG468_SELECT 0x3d /* Programmable chip select */
#define VG468_SELECT_CFG 0x3e /* Chip select configuration */
#define VG468_ATA 0x3f /* ATA control */
/* Flags for VG469_VSENSE */
#define VG469_VSENSE_A_VS1 0x01
#define VG469_VSENSE_A_VS2 0x02
#define VG469_VSENSE_B_VS1 0x04
#define VG469_VSENSE_B_VS2 0x08
/* Flags for VG469_VSELECT */
#define VG469_VSEL_VCC 0x03
#define VG469_VSEL_5V 0x00
#define VG469_VSEL_3V 0x03
#define VG469_VSEL_MAX 0x0c
#define VG469_VSEL_EXT_STAT 0x10
#define VG469_VSEL_EXT_BUS 0x20
#define VG469_VSEL_MIXED 0x40
#define VG469_VSEL_ISA 0x80
/* Flags for VG468_CTL */
#define VG468_CTL_SLOW 0x01 /* 600ns memory timing */
#define VG468_CTL_ASYNC 0x02 /* Asynchronous bus clocking */
#define VG468_CTL_TSSI 0x08 /* Tri-state some outputs */
#define VG468_CTL_DELAY 0x10 /* Card detect debounce */
#define VG468_CTL_INPACK 0x20 /* Obey INPACK signal? */
#define VG468_CTL_POLARITY 0x40 /* VCCEN polarity */
#define VG468_CTL_COMPAT 0x80 /* Compatibility stuff */
#define VG469_CTL_WS_COMPAT 0x04 /* Wait state compatibility */
#define VG469_CTL_STRETCH 0x10 /* LED stretch */
/* Flags for VG468_TIMER */
#define VG468_TIMER_ZEROPWR 0x10 /* Zero power control */
#define VG468_TIMER_SIGEN 0x20 /* Power up */
#define VG468_TIMER_STATUS 0x40 /* Activity timer status */
#define VG468_TIMER_RES 0x80 /* Timer resolution */
#define VG468_TIMER_MASK 0x0f /* Activity timer timeout */
/* Flags for VG468_MISC */
#define VG468_MISC_GPIO 0x04 /* General-purpose IO */
#define VG468_MISC_DMAWSB 0x08 /* DMA wait state control */
#define VG469_MISC_LEDENA 0x10 /* LED enable */
#define VG468_MISC_VADEMREV 0x40 /* Vadem revision control */
#define VG468_MISC_UNLOCK 0x80 /* Unique register lock */
/* Flags for VG469_EXT_MODE_A */
#define VG469_MODE_VPPST 0x03 /* Vpp steering control */
#define VG469_MODE_INT_SENSE 0x04 /* Internal voltage sense */
#define VG469_MODE_CABLE 0x08
#define VG469_MODE_COMPAT 0x10 /* i82365sl B or DF step */
#define VG469_MODE_TEST 0x20
#define VG469_MODE_RIO 0x40 /* Steer RIO to INTR? */
/* Flags for VG469_EXT_MODE_B */
#define VG469_MODE_B_3V 0x01 /* 3.3v for socket B */
/* Data structure for tracking vendor-specific state */
typedef struct vg46x_state_t {
u_char ctl; /* VG468_CTL */
u_char ema; /* VG468_EXT_MODE_A */
} vg46x_state_t;
#endif /* _LINUX_VG468_H */

1148
pcmcia/yacc_config.c Normal file

File diff suppressed because it is too large Load Diff

42
pcmcia/yacc_config.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef YYERRCODE
#define YYERRCODE 256
#endif
#define DEVICE 257
#define CARD 258
#define ANONYMOUS 259
#define TUPLE 260
#define MANFID 261
#define VERSION 262
#define FUNCTION 263
#define PCI 264
#define BIND 265
#define CIS 266
#define TO 267
#define NEEDS_MTD 268
#define MODULE 269
#define OPTS 270
#define CLASS 271
#define REGION 272
#define JEDEC 273
#define DTYPE 274
#define DEFAULT 275
#define MTD 276
#define INCLUDE 277
#define EXCLUDE 278
#define RESERVE 279
#define IRQ_NO 280
#define PORT 281
#define MEMORY 282
#define STRING 283
#define NUMBER 284
#define SOURCE 285
typedef union {
char *str;
u_long num;
struct device_info_t *device;
struct card_info_t *card;
struct mtd_ident_t *mtd;
struct adjust_list_t *adjust;
} YYSTYPE;
extern YYSTYPE yylval;

553
pcmcia/yacc_config.y Normal file
View File

@ -0,0 +1,553 @@
%{
/*
* yacc_config.y 1.57 2002/08/19 03:19:56
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <sys/types.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include "cardmgr.h"
/* If bison: generate nicer error messages */
#define YYERROR_VERBOSE 1
/* from lex_config, for nice error messages */
extern char *current_file;
extern int current_lineno;
void yyerror(char *msg, ...);
static int add_binding(card_info_t *card, char *name, char *class, int fn);
static int add_module(device_info_t *card, char *name);
%}
%token DEVICE CARD ANONYMOUS TUPLE MANFID VERSION FUNCTION PCI
%token BIND CIS TO NEEDS_MTD MODULE OPTS CLASS
%token REGION JEDEC DTYPE DEFAULT MTD
%token INCLUDE EXCLUDE RESERVE IRQ_NO PORT MEMORY
%token STRING NUMBER SOURCE
%union {
char *str;
u_long num;
struct device_info_t *device;
struct card_info_t *card;
struct mtd_ident_t *mtd;
struct adjust_list_t *adjust;
}
%type <str> STRING
%type <num> NUMBER
%type <adjust> adjust resource
%type <device> device needs_mtd module class
%type <card> card anonymous tuple manfid pci version function bind cis
%type <mtd> region jedec dtype default mtd
%%
list: /* nothing */
| list adjust
{
adjust_list_t **tail = &root_adjust;
while (*tail != NULL) tail = &(*tail)->next;
*tail = $2;
}
| list device
{
$2->next = root_device;
root_device = $2;
}
| list mtd
{
if ($2->mtd_type == 0) {
yyerror("no ID method for '%s'", $2->name);
YYERROR;
}
if ($2->module == NULL) {
yyerror("no MTD module for '%s'", $2->name);
YYERROR;
}
$2->next = root_mtd;
root_mtd = $2;
}
| list card
{
if ($2->ident_type == 0) {
yyerror("no ID method for '%s'", $2->name);
YYERROR;
}
if ($2->bindings == 0) {
yyerror("no driver bindings for '%s'", $2->name);
YYERROR;
}
if ($2->ident_type == FUNC_IDENT) {
$2->next = root_func;
root_func = $2;
} else {
$2->next = root_card;
root_card = $2;
}
}
| list opts
| list mtd_opts
| list SOURCE
| list error
;
adjust: INCLUDE resource
{
$2->adj.Action = ADD_MANAGED_RESOURCE;
$$ = $2;
}
| EXCLUDE resource
{
$2->adj.Action = REMOVE_MANAGED_RESOURCE;
$$ = $2;
}
| RESERVE resource
{
$2->adj.Action = ADD_MANAGED_RESOURCE;
$2->adj.Attributes |= RES_RESERVED;
$$ = $2;
}
| adjust ',' resource
{
$3->adj.Action = $1->adj.Action;
$3->adj.Attributes = $1->adj.Attributes;
$3->next = $1;
$$ = $3;
}
;
resource: IRQ_NO NUMBER
{
$$ = calloc(sizeof(adjust_list_t), 1);
$$->adj.Resource = RES_IRQ;
$$->adj.resource.irq.IRQ = $2;
}
| PORT NUMBER '-' NUMBER
{
if (($4 < $2) || ($4 > 0xffff)) {
yyerror("invalid port range 0x%x-0x%x", $2, $4);
YYERROR;
}
$$ = calloc(sizeof(adjust_list_t), 1);
$$->adj.Resource = RES_IO_RANGE;
$$->adj.resource.io.BasePort = $2;
$$->adj.resource.io.NumPorts = $4 - $2 + 1;
}
| MEMORY NUMBER '-' NUMBER
{
if ($4 < $2) {
yyerror("invalid address range 0x%x-0x%x", $2, $4);
YYERROR;
}
$$ = calloc(sizeof(adjust_list_t), 1);
$$->adj.Resource = RES_MEMORY_RANGE;
$$->adj.resource.memory.Base = $2;
$$->adj.resource.memory.Size = $4 - $2 + 1;
}
;
device: DEVICE STRING
{
$$ = calloc(sizeof(device_info_t), 1);
$$->refs = 1;
strcpy($$->dev_info, $2);
free($2);
}
| needs_mtd
| module
| class
;
card: CARD STRING
{
$$ = calloc(sizeof(card_info_t), 1);
$$->refs = 1;
$$->name = $2;
}
| anonymous
| tuple
| manfid
| pci
| version
| function
| bind
| cis
;
anonymous: card ANONYMOUS
{
if ($1->ident_type) {
yyerror("ID method already defined for '%s'", $1->name);
YYERROR;
}
if (blank_card) {
yyerror("Anonymous card already defined");
YYERROR;
}
$1->ident_type = BLANK_IDENT;
blank_card = $1;
}
;
tuple: card TUPLE NUMBER ',' NUMBER ',' STRING
{
if ($1->ident_type) {
yyerror("ID method already defined for '%s'", $1->name);
YYERROR;
}
$1->ident_type = TUPLE_IDENT;
$1->id.tuple.code = $3;
$1->id.tuple.ofs = $5;
$1->id.tuple.info = $7;
}
;
manfid: card MANFID NUMBER ',' NUMBER
{
if ($1->ident_type & (EXCL_IDENT|MANFID_IDENT)) {
yyerror("ID method already defined for '%s'", $1->name);
YYERROR;
}
$1->ident_type |= MANFID_IDENT;
$1->manfid.manf = $3;
$1->manfid.card = $5;
}
pci: card PCI NUMBER ',' NUMBER
{
if ($1->ident_type) {
yyerror("ID method already defined for '%s'", $1->name);
YYERROR;
}
$1->ident_type = PCI_IDENT;
$1->manfid.manf = $3;
$1->manfid.card = $5;
}
version: card VERSION STRING
{
if ($1->ident_type & (EXCL_IDENT|VERS_1_IDENT)) {
yyerror("ID method already defined for '%s'", $1->name);
YYERROR;
}
$1->ident_type |= VERS_1_IDENT;
$1->id.vers.ns = 1;
$1->id.vers.pi[0] = $3;
}
| version ',' STRING
{
if ($1->id.vers.ns == 4) {
yyerror("too many version strings for '%s'", $1->name);
YYERROR;
}
$1->id.vers.pi[$1->id.vers.ns] = $3;
$1->id.vers.ns++;
}
;
function: card FUNCTION NUMBER
{
if ($1->ident_type) {
yyerror("ID method already defined for '%s'", $1->name);
YYERROR;
}
$1->ident_type = FUNC_IDENT;
$1->id.func.funcid = $3;
}
;
cis: card CIS STRING
{ $1->cis_file = strdup($3); }
;
bind: card BIND STRING
{
if (add_binding($1, $3, NULL, 0) != 0)
YYERROR;
}
| card BIND STRING CLASS STRING
{
if (add_binding($1, $3, $5, 0) != 0)
YYERROR;
}
| card BIND STRING TO NUMBER
{
if (add_binding($1, $3, NULL, $5) != 0)
YYERROR;
}
| card BIND STRING CLASS STRING TO NUMBER
{
if (add_binding($1, $3, $5, $7) != 0)
YYERROR;
}
| bind ',' STRING
{
if (add_binding($1, $3, NULL, 0) != 0)
YYERROR;
}
| bind ',' STRING CLASS STRING
{
if (add_binding($1, $3, $5, 0) != 0)
YYERROR;
}
| bind ',' STRING TO NUMBER
{
if (add_binding($1, $3, NULL, $5) != 0)
YYERROR;
}
| bind ',' STRING CLASS STRING TO NUMBER
{
if (add_binding($1, $3, $5, $7) != 0)
YYERROR;
}
;
needs_mtd: device NEEDS_MTD
{
$1->needs_mtd = 1;
}
;
opts: MODULE STRING OPTS STRING
{
device_info_t *d;
int i, found = 0;
for (d = root_device; d; d = d->next) {
for (i = 0; i < d->modules; i++)
if (strcmp($2, d->module[i]) == 0) break;
if (i < d->modules) {
if (d->opts[i])
free(d->opts[i]);
d->opts[i] = strdup($4);
found = 1;
}
}
free($2); free($4);
if (!found) {
yyerror("module name '%s' not found", $2);
YYERROR;
}
}
;
module: device MODULE STRING
{
if (add_module($1, $3) != 0)
YYERROR;
}
| module OPTS STRING
{
if ($1->opts[$1->modules-1] == NULL) {
$1->opts[$1->modules-1] = $3;
} else {
yyerror("too many module options for '%s'",
$1->module[$1->modules-1]);
YYERROR;
}
}
| module ',' STRING
{
if (add_module($1, $3) != 0)
YYERROR;
}
;
class: device CLASS STRING
{
if ($1->class != NULL) {
yyerror("extra class string '%s'", $3);
YYERROR;
}
$1->class = $3;
}
;
region: REGION STRING
{
$$ = calloc(sizeof(mtd_ident_t), 1);
$$->refs = 1;
$$->name = $2;
}
| dtype
| jedec
| default
;
dtype: region DTYPE NUMBER
{
if ($1->mtd_type) {
yyerror("ID method already defined for '%s'", $1->name);
YYERROR;
}
$1->mtd_type = DTYPE_MTD;
$1->dtype = $3;
}
;
jedec: region JEDEC NUMBER NUMBER
{
if ($1->mtd_type) {
yyerror("ID method already defined for '%s'", $1->name);
YYERROR;
}
$1->mtd_type = JEDEC_MTD;
$1->jedec_mfr = $3;
$1->jedec_info = $4;
}
;
default: region DEFAULT
{
if ($1->mtd_type) {
yyerror("ID method already defined for '%s'", $1->name);
YYERROR;
}
if (default_mtd) {
yyerror("Default MTD already defined");
YYERROR;
}
$1->mtd_type = DEFAULT_MTD;
default_mtd = $1;
}
;
mtd: region MTD STRING
{
if ($1->module != NULL) {
yyerror("extra MTD entry for '%s'", $1->name);
YYERROR;
}
$1->module = $3;
}
| mtd OPTS STRING
{
if ($1->opts == NULL) {
$1->opts = $3;
} else {
yyerror("too many module options for '%s'", $1->module);
YYERROR;
}
}
;
mtd_opts: MTD STRING OPTS STRING
{
mtd_ident_t *m;
int found = 0;
for (m = root_mtd; m; m = m->next)
if (strcmp($2, m->module) == 0) break;
if (m) {
if (m->opts) free(m->opts);
m->opts = strdup($4);
found = 1;
}
free($2); free($4);
if (!found) {
yyerror("MTD name '%s' not found", $2);
YYERROR;
}
}
;
%%
void yyerror(char *msg, ...)
{
va_list ap;
char str[256];
va_start(ap, msg);
sprintf(str, "error in file '%s' line %d: ",
current_file, current_lineno);
vsprintf(str+strlen(str), msg, ap);
#if YYDEBUG
fprintf(stderr, "%s\n", str);
#else
syslog(LOG_ERR, "%s", str);
#endif
va_end(ap);
}
static int add_binding(card_info_t *card, char *name, char *class, int fn)
{
device_info_t *dev = root_device;
if (card->bindings == MAX_BINDINGS) {
yyerror("too many bindings\n");
return -1;
}
for (; dev; dev = dev->next)
if (strcmp((char *)dev->dev_info, name) == 0) break;
if (dev == NULL) {
yyerror("unknown device '%s'", name);
return -1;
}
card->device[card->bindings] = dev;
card->dev_fn[card->bindings] = fn;
if (class)
card->class[card->bindings] = strdup(class);
card->bindings++;
free(name);
return 0;
}
static int add_module(device_info_t *dev, char *name)
{
if (dev->modules == MAX_MODULES) {
yyerror("too many modules for '%s'", dev->dev_info);
return -1;
}
dev->module[dev->modules] = name;
dev->opts[dev->modules] = NULL;
dev->modules++;
return 0;
}
#if YYDEBUG
adjust_list_t *root_adjust = NULL;
device_info_t *root_device = NULL;
card_info_t *root_card = NULL, *blank_card = NULL, *root_func = NULL;
mtd_ident_t *root_mtd = NULL, *default_mtd = NULL;
void main(int argc, char *argv[])
{
yydebug = 1;
if (argc > 1)
parse_configfile(argv[1]);
}
#endif

46
pcmcia_config.patch Normal file
View File

@ -0,0 +1,46 @@
--- pcmcia/config~ Thu Aug 31 00:05:25 2000
+++ pcmcia/config Fri Sep 17 17:25:35 1999
@@ -34,7 +34,7 @@
class "cdrom" module "oti12_cs"
device "pcnet_cs"
- class "network" module "net/8390", "pcnet_cs"
+ class "network" module "8390", "pcnet_cs"
device "axnet_cs"
class "network" module "net/8390", "axnet_cs"
@@ -64,25 +64,25 @@
class "ftl" module "ftl_cs"
device "serial_cs"
- class "serial" module "serial_cs"
+ class "serial" module "serial", "serial_cs"
device "parport_cs"
class "parport" module "parport_cs"
device "qlogic_cs"
- class "scsi" module "qlogic_cs"
-
+ class "scsi" module "scsi_mod", "qlogic_cs"
+
device "aha152x_cs"
- class "scsi" module "aha152x_cs"
-
+ class "scsi" module "scsi_mod", "aha152x_cs"
+
device "fdomain_cs"
- class "scsi" module "fdomain_cs"
-
+ class "scsi" module "scsi_mod", "fdomain_cs"
+
device "sym53c500_cs"
- class "scsi" module "sym53c500_cs"
+ class "scsi" module "scsi_mod", "sym53c500_cs"
device "ide-cs"
- class "ide" module "ide-cs"
+ class "ide" module "ide-mod", "ide-probe", "ide-cs"
device "fmvj18x_cs"
class "network" module "fmvj18x_cs"

658
probing.c Normal file
View File

@ -0,0 +1,658 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
/*
* This contains stuff related to probing:
* (1) any (actually only SCSI, NET, CPQ, USB Controllers) devices (autoprobe for PCI and USB)
* (2) IDE media
* (3) SCSI media
* (4) ETH devices
*/
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
// #include <sys/socket.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include "stage1.h"
#include "log.h"
#include "frontend.h"
#include "modules.h"
#include "pci-resource/pci-ids.h"
#ifdef ENABLE_USB
#include "usb-resource/usb-ids.h"
#endif
#include "probing.h"
struct media_info {
char * name;
char * model;
enum media_type type;
};
static void warning_insmod_failed(enum insmod_return r)
{
if (IS_AUTOMATIC && r == INSMOD_FAILED_FILE_NOT_FOUND)
return;
if (r != INSMOD_OK) {
if (r == INSMOD_FAILED_FILE_NOT_FOUND)
stg1_error_message("This floppy doesn't contain the driver.");
else
stg1_error_message("Warning, installation of driver failed. (please include msg from <Alt-F3> for bugreports)");
}
}
#ifndef DISABLE_NETWORK
struct net_description_elem
{
char * intf_name;
char * intf_description;
};
static struct net_description_elem net_descriptions[50];
static int net_descr_number = 0;
static char * intf_descr_for_discover = NULL;
static char * net_intf_too_early_name[50]; /* for modules providing more than one net intf */
static int net_intf_too_early_number = 0;
static int net_intf_too_early_ptr = 0;
void prepare_intf_descr(const char * intf_descr)
{
intf_descr_for_discover = strdup(intf_descr);
}
void net_discovered_interface(char * intf_name)
{
if (!intf_descr_for_discover) {
net_intf_too_early_name[net_intf_too_early_number++] = strdup(intf_name);
return;
}
if (!intf_name) {
if (net_intf_too_early_ptr >= net_intf_too_early_number) {
log_message("NET: was expecting another network interface (broken net module?)");
return;
}
net_descriptions[net_descr_number].intf_name = net_intf_too_early_name[net_intf_too_early_ptr++];
}
else
net_descriptions[net_descr_number].intf_name = strdup(intf_name);
net_descriptions[net_descr_number].intf_description = strdup(intf_descr_for_discover);
intf_descr_for_discover = NULL;
net_descr_number++;
}
char * get_net_intf_description(char * intf_name)
{
int i;
for (i = 0; i < net_descr_number ; i++)
if (!strcmp(net_descriptions[i].intf_name, intf_name))
return net_descriptions[i].intf_description;
return strdup("unknown");
}
#endif
static void probe_that_type(enum driver_type type)
{
if (IS_EXPERT) {
ask_insmod(type);
return;
}
/* ---- PCI probe ---------------------------------------------- */
{
FILE * f;
int len = 0;
char buf[200];
struct pci_module_map * pcidb = NULL;
switch (type) {
#ifndef DISABLE_MEDIAS
case SCSI_ADAPTERS:
pcidb = medias_pci_ids;
len = medias_num_ids;
break;
#endif
#ifndef DISABLE_NETWORK
#ifndef DISABLE_PCINET
case NETWORK_DEVICES:
pcidb = network_pci_ids;
len = network_num_ids;
break;
#endif
#endif
#ifdef ENABLE_USB
case USB_CONTROLLERS:
pcidb = usb_pci_ids;
len = usb_num_ids;
break;
#endif
default:
goto end_pci_probe;
}
if (!(f = fopen("/proc/bus/pci/devices", "rb"))) {
log_message("PCI: could not open proc file");
goto end_pci_probe;
}
while (1) {
int i, garb, vendor, device;
if (!fgets(buf, sizeof(buf), f)) break;
sscanf(buf, "%x %x", &garb, &vendor);
device = vendor & 0xFFFF; /* because scanf from dietlibc does not support %4f */
vendor = (vendor >> 16) & 0xFFFF;
log_message("PCI-test: device %04x %04x\n", vendor, device);
for (i = 0; i < len; i++) {
if (pcidb[i].vendor == vendor && pcidb[i].device == device) {
log_message("PCI: device %04x %04x is \"%s\" (%s)", vendor, device, pcidb[i].name, pcidb[i].module);
#ifndef DISABLE_MEDIAS
if (type == SCSI_ADAPTERS) {
int wait_msg = 0;
enum insmod_return failed;
if (IS_AUTOMATIC) {
wait_message("Loading driver for SCSI adapter:\n \n%s", pcidb[i].name);
wait_msg = 1;
} else
stg1_info_message("About to load driver for SCSI adapter:\n \n%s", pcidb[i].name);
failed = my_insmod(pcidb[i].module, SCSI_ADAPTERS, NULL);
if (wait_msg)
remove_wait_message();
warning_insmod_failed(failed);
}
#endif
#ifndef DISABLE_NETWORK
if (type == NETWORK_DEVICES) {
stg1_info_message("About to load driver for network device:\n \n%s", pcidb[i].name);
prepare_intf_descr(pcidb[i].name);
warning_insmod_failed(my_insmod(pcidb[i].module, NETWORK_DEVICES, NULL));
if (intf_descr_for_discover) /* for modules providing more than one net intf */
net_discovered_interface(NULL);
}
#endif
#ifdef ENABLE_USB
if (type == USB_CONTROLLERS)
my_insmod(pcidb[i].module, USB_CONTROLLERS, NULL);
#endif
}
}
}
fclose(f);
end_pci_probe:
}
#ifdef ENABLE_USB
/* ---- USB probe ---------------------------------------------- */
{
static int already_probed_usb_controllers = 0;
static int already_mounted_usbdev = 0;
FILE * f;
int len = 0;
char buf[200];
struct usb_module_map * usbdb = NULL;
switch (type) {
#ifdef ENABLE_USBNET
case NETWORK_DEVICES:
usbdb = usbnet_usb_ids;
len = usbnet_usb_num_ids;
break;
#endif
default:
goto end_usb_probe;
}
if (!already_probed_usb_controllers) {
already_probed_usb_controllers = 1;
probe_that_type(USB_CONTROLLERS);
}
if (!already_mounted_usbdev) {
already_mounted_usbdev = 1;
if (mount("/proc/bus/usb", "/proc/bus/usb", "usbdevfs", 0, NULL)) {
log_message("USB: couldn't mount /proc/bus/usb");
goto end_usb_probe;
}
wait_message("Waiting for USB stuff to show up.");
sleep(2); /* sucking background work */
remove_wait_message();
}
if (!(f = fopen("/proc/bus/usb/devices", "rb"))) {
log_message("USB: could not open proc file");
goto end_usb_probe;
}
while (1) {
int i, vendor, id;
if (!fgets(buf, sizeof(buf), f)) break;
if (strstr(buf, "Keyboard")) {
my_insmod("usbkbd", ANY_DRIVER_TYPE, NULL);
my_insmod("keybdev", ANY_DRIVER_TYPE, NULL);
}
if (sscanf(buf, "P: Vendor=%x ProdID=%x", &vendor, &id) != 2)
continue;
for (i = 0; i < len; i++) {
if (usbdb[i].vendor == vendor && usbdb[i].id == id) {
log_message("USB: device %04x %04x is \"%s\" (%s)", vendor, id, usbdb[i].name, usbdb[i].module);
#ifdef ENABLE_USBNET
if (type == NETWORK_DEVICES) {
stg1_info_message("About to load driver for usb network device:\n \n%s", usbdb[i].name);
prepare_intf_descr(usbdb[i].name);
warning_insmod_failed(my_insmod(usbdb[i].module, NETWORK_DEVICES, NULL));
if (intf_descr_for_discover) /* for modules providing more than one net intf */
net_discovered_interface(NULL);
}
#endif
}
}
}
fclose(f);
end_usb_probe:
}
#endif
}
#ifndef DISABLE_MEDIAS
static struct media_info * medias = NULL;
static void find_media(void)
{
char b[50];
char buf[5000];
struct media_info tmp[50];
int count;
int fd;
if (!medias)
probe_that_type(SCSI_ADAPTERS);
else
free(medias); /* that does not free the strings, by the way */
/* ----------------------------------------------- */
log_message("looking for ide media");
count = 0;
strcpy(b, "/proc/ide/hd");
for (b[12] = 'a'; b[12] <= 'h'; b[12]++) {
int i;
char ide_disk[] = "disk";
char ide_cdrom[] = "cdrom";
char ide_tape[] = "tape";
char ide_floppy[] = "floppy";
/* first, test if file exists (will tell if attached medium exists) */
b[13] = '\0';
if (access(b, R_OK))
continue;
tmp[count].name = strdup("hda");
tmp[count].name[2] = b[12];
/* media type */
strcpy(b + 13, "/media");
fd = open(b, O_RDONLY);
if (fd == -1) {
log_message("failed to open %s for reading", b);
continue;
}
i = read(fd, buf, sizeof(buf));
if (i == -1) {
log_message("failed to read %s", b);
continue;
}
buf[i] = '\0';
close(fd);
if (ptr_begins_static_str(buf, ide_disk))
tmp[count].type = DISK;
else if (ptr_begins_static_str(buf, ide_cdrom))
tmp[count].type = CDROM;
else if (ptr_begins_static_str(buf, ide_tape))
tmp[count].type = TAPE;
else if (ptr_begins_static_str(buf, ide_floppy))
tmp[count].type = FLOPPY;
else
tmp[count].type = UNKNOWN_MEDIA;
/* media model */
strcpy(b + 13, "/model");
fd = open(b, O_RDONLY);
if (fd == -1) {
log_message("failed to open %s for reading", b);
continue;
}
i = read(fd, buf, sizeof(buf));
if (i <= 0) {
log_message("failed to read %s", b);
tmp[count].model = strdup("(none)");
}
else {
buf[i-1] = '\0'; /* eat the \n */
tmp[count].model = strdup(buf);
}
close(fd);
log_message("IDE/%d: %s is a %s", tmp[count].type, tmp[count].name, tmp[count].model);
count++;
}
/* ----------------------------------------------- */
log_message("looking for scsi media");
fd = open("/proc/scsi/scsi", O_RDONLY);
if (fd != -1) {
enum { SCSI_TOP, SCSI_HOST, SCSI_VENDOR, SCSI_TYPE } state = SCSI_TOP;
char * start, * chptr, * next, * end;
char scsi_disk_count = 'a';
char scsi_cdrom_count = '0';
char scsi_tape_count = '0';
char scsi_no_devices[] = "Attached devices: none";
char scsi_some_devices[] = "Attached devices: ";
char scsi_host[] = "Host: ";
char scsi_vendor[] = " Vendor: ";
int i = read(fd, &buf, sizeof(buf)-1);
if (i < 1) {
close(fd);
goto end_scsi;
}
close(fd);
buf[i] = '\0';
if (ptr_begins_static_str(buf, scsi_no_devices))
goto end_scsi;
start = buf;
while (*start) {
char tmp_model[50];
char tmp_name[10];
chptr = start;
while (*chptr != '\n') chptr++;
*chptr = '\0';
next = chptr + 1;
switch (state) {
case SCSI_TOP:
if (!ptr_begins_static_str(start, scsi_some_devices))
goto end_scsi;
state = SCSI_HOST;
break;
case SCSI_HOST:
if (!ptr_begins_static_str(start, scsi_host))
goto end_scsi;
state = SCSI_VENDOR;
break;
case SCSI_VENDOR:
if (!ptr_begins_static_str(start, scsi_vendor))
goto end_scsi;
/* (1) Grab Vendor info */
start += 10;
end = chptr = strstr(start, "Model:");
if (!chptr)
goto end_scsi;
chptr--;
while (*chptr == ' ')
chptr--;
if (*chptr == ':') {
chptr++;
*(chptr + 1) = '\0';
strcpy(tmp_model,"(unknown)");
} else {
*(chptr + 1) = '\0';
strcpy(tmp_model, start);
}
/* (2) Grab Model info */
start = end;
start += 7;
chptr = strstr(start, "Rev:");
if (!chptr)
goto end_scsi;
chptr--;
while (*chptr == ' ') chptr--;
*(chptr + 1) = '\0';
strcat(tmp_model, " ");
strcat(tmp_model, start);
tmp[count].model = strdup(tmp_model);
state = SCSI_TYPE;
break;
case SCSI_TYPE:
if (strncmp(" Type:", start, 7))
goto end_scsi;
*tmp_name = '\0';
if (strstr(start, "Direct-Access")) {
sprintf(tmp_name, "sd%c", scsi_disk_count++);
tmp[count].type = DISK;
} else if (strstr(start, "Sequential-Access")) {
sprintf(tmp_name, "st%c", scsi_tape_count++);
tmp[count].type = TAPE;
} else if (strstr(start, "CD-ROM")) {
sprintf(tmp_name, "sr%c", scsi_cdrom_count++);
tmp[count].type = CDROM;
}
if (*tmp_name) {
tmp[count].name = strdup(tmp_name);
log_message("SCSI/%d: %s is a %s", tmp[count].type, tmp[count].name, tmp[count].model);
count++;
}
state = SCSI_HOST;
}
start = next;
}
end_scsi:
}
/* ----------------------------------------------- */
log_message("looking for Compaq Smart Array media");
{
char * procfiles[] = { "/proc/driver/cpqarray/ida0", "/proc/driver/cciss/cciss0", // 2.4 style
"/proc/array/ida", "/proc/cciss/cciss", // 2.2 style
NULL };
static char cpq_descr[] = "Compaq RAID logical disk";
char ** procfile = procfiles;
FILE * f;
while (procfile && *procfile && (f = fopen(*procfile, "rb"))) {
while (fgets(buf, sizeof(buf), f)) {
if (ptr_begins_static_str(buf, "ida/") || ptr_begins_static_str(buf, "cciss/")) {
char * end = strchr(buf, ':');
if (!end)
log_message("Inconsistency in %s, line:\n%s", *procfile, buf);
else {
*end = '\0';
tmp[count].name = strdup(buf);
tmp[count].type = DISK;
tmp[count].model = cpq_descr;
log_message("CPQ: found %s", tmp[count].name);
count++;
}
}
}
fclose(f);
procfile++;
}
}
/* ----------------------------------------------- */
log_message("looking for DAC960");
{
FILE * f;
if ((f = fopen("/tmp/syslog", "rb"))) {
while (fgets(buf, sizeof(buf), f)) {
char * start;
if ((start = strstr(buf, "/dev/rd/"))) {
char * end = strchr(start, ':');
if (!end)
log_message("Inconsistency in syslog, line:\n%s", buf);
else {
*end = '\0';
tmp[count].name = strdup(start+5);
tmp[count].type = DISK;
start = end + 2;
end = strchr(start, ',');
if (end) {
*end = '\0';
tmp[count].model = strdup(start);
} else
tmp[count].model = "(unknown)";
log_message("DAC960: found %s (%s)", tmp[count].name, tmp[count].model);
count++;
}
}
}
fclose(f);
}
}
/* ----------------------------------------------- */
tmp[count].name = NULL;
count++;
medias = memdup(tmp, sizeof(struct media_info) * count);
}
/* Finds by media */
void get_medias(enum media_type media, char *** names, char *** models)
{
struct media_info * m;
char * tmp_names[50];
char * tmp_models[50];
int count;
find_media();
m = medias;
count = 0;
while (m && m->name) {
if (m->type == media) {
tmp_names[count] = strdup(m->name);
tmp_models[count++] = strdup(m->model);
}
m++;
}
tmp_names[count] = NULL;
tmp_models[count++] = NULL;
*names = memdup(tmp_names, sizeof(char *) * count);
*models = memdup(tmp_models, sizeof(char *) * count);
}
#endif /* DISABLE_MEDIAS */
#ifndef DISABLE_NETWORK
int net_device_available(char * device) {
struct ifreq req;
int s;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
log_perror(device);
return 0;
}
strcpy(req.ifr_name, device);
if (ioctl(s, SIOCGIFFLAGS, &req)) {
/* if we can't get the flags, the networking device isn't available */
close(s);
return 0;
}
close(s);
return 1;
}
char ** get_net_devices(void)
{
char * devices[] = {
"eth0", "eth1", "eth2", "eth3", "eth4", "eth5",
"tr0",
"plip0", "plip1", "plip2",
"fddi0",
#ifdef ENABLE_USBNET
"usb0", "usb1", "usb2", "usb3",
#endif
NULL
};
char ** ptr = devices;
char * tmp[50];
int i = 0;
static int already_probed = 0;
if (!already_probed) {
already_probed = 1; /* cut off loop brought by: probe_that_type => my_insmod => get_net_devices */
probe_that_type(NETWORK_DEVICES);
}
while (ptr && *ptr) {
if (net_device_available(*ptr))
tmp[i++] = strdup(*ptr);
ptr++;
}
tmp[i++] = NULL;
return memdup(tmp, sizeof(char *) * i);
}
#endif /* DISABLE_NETWORK */

36
probing.h Normal file
View File

@ -0,0 +1,36 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#ifndef _PROBING_H_
#define _PROBING_H_
enum media_type { CDROM, DISK, FLOPPY, TAPE, UNKNOWN_MEDIA };
enum driver_type { SCSI_ADAPTERS, NETWORK_DEVICES, USB_CONTROLLERS, ANY_DRIVER_TYPE };
void get_medias(enum media_type media, char *** names, char *** models);
char ** get_net_devices(void);
void net_discovered_interface(char * intf_name);
char * get_net_intf_description(char * intf_name);
void prepare_intf_descr(const char * intf_descr);
#endif

Binary file not shown.

Binary file not shown.

BIN
stage1-data/stage1.tar.bz2 Normal file

Binary file not shown.

439
stage1.c Normal file
View File

@ -0,0 +1,439 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* View the homepage: http://us.mandrakesoft.com/~gc/html/stage1.html
*
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <stdarg.h>
#include <signal.h>
#include "stage1.h"
#include "log.h"
#include "probing.h"
#include "frontend.h"
#include "modules.h"
#include "tools.h"
#include "automatic.h"
#include "mount.h"
#include "insmod.h"
#ifdef ENABLE_PCMCIA
#include "pcmcia/pcmcia.h"
#endif
#ifndef DISABLE_CDROM
#include "cdrom.h"
#endif
#ifndef DISABLE_NETWORK
#include "network.h"
#endif
#ifndef DISABLE_DISK
#include "disk.h"
#endif
/************************************************************
* globals */
char * method_name;
void fatal_error(char *msg)
{
printf("FATAL ERROR IN STAGE1: %s\n\nI can't recover from this.\nYou may reboot your system.\n", msg);
while (1);
}
/************************************************************
* special frontend functs
* (the principle is to not pollute frontend code with stage1-specific stuff) */
void stg1_error_message(char *msg, ...)
{
va_list args;
va_start(args, msg);
log_message("unsetting automatic");
unset_param(MODE_AUTOMATIC);
verror_message(msg, args);
va_end(args);
}
void stg1_info_message(char *msg, ...)
{
va_list args;
va_start(args, msg);
if (IS_AUTOMATIC) {
vlog_message(msg, args);
return;
}
vinfo_message(msg, args);
va_end(args);
}
/************************************************************
* spawns a shell on console #2 */
static void spawn_shell(void)
{
#ifdef SPAWN_SHELL
int fd;
char * shell_name[] = { "/tmp/sh", NULL };
log_message("spawning a shell");
if (!IS_TESTING) {
fd = open("/dev/tty2", O_RDWR);
if (fd == -1) {
log_message("cannot open /dev/tty2 -- no shell will be provided");
return;
}
else if (access(shell_name[0], X_OK)) {
log_message("cannot open shell - %s doesn't exist", shell_name[0]);
return;
}
if (!fork()) {
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
close(fd);
setsid();
if (ioctl(0, TIOCSCTTY, NULL))
log_perror("could not set new controlling tty");
execve(shell_name[0], shell_name, grab_env());
log_message("execve of %s failed: %s", shell_name[0], strerror(errno));
exit(-1);
}
close(fd);
}
#endif
}
char * interactive_fifo = "/tmp/stage1-fifo";
static pid_t interactive_pid = 0;
/* spawns my small interactive on console #6 */
static void spawn_interactive(void)
{
#ifdef SPAWN_INTERACTIVE
int fd;
char * dev = "/dev/tty6";
printf("spawning my interactive on %s\n", dev);
if (!IS_TESTING) {
fd = open(dev, O_RDWR);
if (fd == -1) {
printf("cannot open %s -- no interactive\n", dev);
return;
}
if (mkfifo(interactive_fifo, O_RDWR)) {
printf("cannot create fifo -- no interactive\n");
return;
}
if (!(interactive_pid = fork())) {
int fif_out;
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
close(fd);
setsid();
if (ioctl(0, TIOCSCTTY, NULL))
perror("could not set new controlling tty");
fif_out = open(interactive_fifo, O_WRONLY);
printf("Please enter your command (availables: [+,-] [rescue,expert]).\n");
while (1) {
char s[50];
int i = 0;
printf("? ");
fflush(stdout);
read(0, &(s[i++]), 1);
fcntl(0, F_SETFL, O_NONBLOCK);
while (read(0, &(s[i++]), 1) > 0 && i < sizeof(s));
fcntl(0, F_SETFL, 0);
write(fif_out, s, i-2);
printf("Ok.\n");
}
}
close(fd);
}
#endif
}
/************************************************************
*/
static void expert_third_party_modules(void)
{
enum return_type results;
char * floppy_mount_location = "/tmp/floppy";
char ** modules;
char final_name[500];
char * choice;
int rc;
char * questions[] = { "Options", NULL };
static char ** answers = NULL;
results = ask_yes_no("If you want to insert third-party kernel modules, insert "
"a Linux (ext2fs) formatted floppy containing the modules and confirm. Otherwise, select \"no\".");;
if (results != RETURN_OK)
return;
my_insmod("floppy", ANY_DRIVER_TYPE, NULL);
if (my_mount("/dev/fd0", floppy_mount_location, "ext2", 0) == -1) {
stg1_error_message("I can't find a Linux ext2 floppy in first floppy drive.");
return expert_third_party_modules();
}
modules = list_directory(floppy_mount_location);
if (!modules || !*modules) {
stg1_error_message("No modules found on floppy disk.");
umount(floppy_mount_location);
return expert_third_party_modules();
}
results = ask_from_list("Which driver would you like to insmod?", modules, &choice);
if (results != RETURN_OK) {
umount(floppy_mount_location);
return;
}
sprintf(final_name, "%s/%s", floppy_mount_location, choice);
results = ask_from_entries("Please enter the options:", questions, &answers, 24, NULL);
if (results != RETURN_OK) {
umount(floppy_mount_location);
return expert_third_party_modules();
}
rc = insmod_call(final_name, answers[0]);
umount(floppy_mount_location);
if (rc) {
log_message("\tfailed");
stg1_error_message("Insmod failed.");
}
return expert_third_party_modules();
}
static void handle_pcmcia(char ** pcmcia_adapter)
{
#ifdef ENABLE_PCMCIA
*pcmcia_adapter = pcmcia_probe();
if (!*pcmcia_adapter) {
log_message("no pcmcia adapter found");
return;
}
my_insmod("pcmcia_core", ANY_DRIVER_TYPE, "probe_io=0");
my_insmod(*pcmcia_adapter, ANY_DRIVER_TYPE, NULL);
my_insmod("ds", ANY_DRIVER_TYPE, NULL);
/* call to cardmgr takes time, let's use the wait message */
wait_message("Enabling PCMCIA extension cards...");
log_message("cardmgr rc: %d", cardmgr_call());
remove_wait_message();
#endif
}
/************************************************************
*/
static enum return_type method_select_and_prepare(void)
{
enum return_type results;
char * choice;
char * means[10], * means_auto[10];
int i;
#ifndef DISABLE_DISK
char * disk_install = "Hard disk"; char * disk_install_auto = "disk";
#endif
#ifndef DISABLE_CDROM
char * cdrom_install = "CDROM drive"; char * cdrom_install_auto = "cdrom";
#endif
#ifndef DISABLE_NETWORK
char * network_nfs_install = "NFS server"; char * network_nfs_install_auto = "nfs";
char * network_ftp_install = "FTP server"; char * network_ftp_install_auto = "ftp";
char * network_http_install = "HTTP server"; char * network_http_install_auto = "http";
#endif
i = 0;
#ifndef DISABLE_NETWORK
means[i] = network_nfs_install; means_auto[i++] = network_nfs_install_auto;
means[i] = network_ftp_install; means_auto[i++] = network_ftp_install_auto;
means[i] = network_http_install; means_auto[i++] = network_http_install_auto;
#endif
#ifndef DISABLE_CDROM
means[i] = cdrom_install; means_auto[i++] = cdrom_install_auto;
#endif
#ifndef DISABLE_DISK
means[i] = disk_install; means_auto[i++] = disk_install_auto;
#endif
means[i] = NULL;
results = ask_from_list_auto("Please choose the installation method.", means, &choice, "method", means_auto);
if (results != RETURN_OK)
return method_select_and_prepare();
results = RETURN_ERROR;
#ifndef DISABLE_CDROM
if (!strcmp(choice, cdrom_install))
results = cdrom_prepare();
#endif
#ifndef DISABLE_DISK
if (!strcmp(choice, disk_install))
results = disk_prepare();
#endif
#ifndef DISABLE_NETWORK
if (!strcmp(choice, network_nfs_install))
results = nfs_prepare();
if (!strcmp(choice, network_ftp_install))
results = ftp_prepare();
if (!strcmp(choice, network_http_install))
results = http_prepare();
#endif
if (results != RETURN_OK)
return method_select_and_prepare();
return RETURN_OK;
}
int main(int argc, char **argv, char **env)
{
enum return_type ret;
char ** argptr;
char * stage2_args[30];
char * pcmcia_adapter = NULL;
if (getpid() > 50)
set_param(MODE_TESTING);
spawn_interactive();
open_log();
log_message("welcome to the " DISTRIB_NAME " install (mdk-stage1, version " VERSION " built " __DATE__ " " __TIME__")");
process_cmdline();
handle_env(env);
spawn_shell();
init_modules_insmoding();
init_frontend("Welcome to " DISTRIB_NAME " (" VERSION ") " __DATE__ " " __TIME__);
if (IS_EXPERT)
expert_third_party_modules();
if (IS_UPDATEMODULES)
update_modules();
handle_pcmcia(&pcmcia_adapter);
if (IS_CHANGEDISK)
stg1_info_message("You are starting the installation with an alternate booting method. "
"Please change your disk, and insert the Installation disk.");
if (IS_RESCUE && total_memory() < MEM_LIMIT_RESCUE) {
stg1_error_message("You are starting the rescue with a low memory configuration. "
"From that point, experience showed us that the program may stop "
"or crash at any point without immediate proper reason. Continue at "
"your own risk. Alternatively, you may reboot your system now.");
}
ret = method_select_and_prepare();
finish_frontend();
close_log();
if (ret != RETURN_OK)
fatal_error("could not select an installation method");
if (!IS_RAMDISK) {
if (symlink(IMAGE_LOCATION LIVE_LOCATION, STAGE2_LOCATION) != 0) {
printf("symlink from " IMAGE_LOCATION LIVE_LOCATION " to " STAGE2_LOCATION " failed");
fatal_error(strerror(errno));
}
}
if (interactive_pid != 0)
kill(interactive_pid, 9);
if (IS_RESCUE)
return 66;
if (IS_TESTING)
return 0;
argptr = stage2_args;
*argptr++ = "/usr/bin/runinstall2";
*argptr++ = "--method";
*argptr++ = method_name;
if (pcmcia_adapter) {
*argptr++ = "--pcmcia";
*argptr++ = pcmcia_adapter;
}
if (disable_modules)
*argptr++ = "--blank";
*argptr++ = NULL;
execve(stage2_args[0], stage2_args, grab_env());
printf("error in exec of stage2 :-(\n");
fatal_error(strerror(errno));
return 0; /* shut up compiler (we can't get here anyway!) */
}

60
stage1.h Normal file
View File

@ -0,0 +1,60 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#ifndef _STAGE1_H_
#define _STAGE1_H_
#include "config-stage1.h"
#include "tools.h"
/* Some global stuff */
extern char * method_name;
extern char * interactive_fifo;
#define MODE_TESTING (1 << 0)
#define MODE_EXPERT (1 << 1)
#define MODE_RESCUE (1 << 3)
#define MODE_AUTOMATIC (1 << 4)
#define MODE_LOWMEM (1 << 5)
#define MODE_SPECIAL_STAGE2 (1 << 8)
#define MODE_RAMDISK (1 << 9)
#define MODE_CHANGEDISK (1 << 10)
#define MODE_UPDATEMODULES (1 << 11)
#define IS_TESTING (get_param(MODE_TESTING))
#define IS_EXPERT (get_param(MODE_EXPERT))
#define IS_RESCUE (get_param(MODE_RESCUE))
#define IS_AUTOMATIC (get_param(MODE_AUTOMATIC))
#define IS_LOWMEM (get_param(MODE_LOWMEM))
#define IS_SPECIAL_STAGE2 (get_param(MODE_SPECIAL_STAGE2))
#define IS_RAMDISK (get_param(MODE_RAMDISK))
#define IS_CHANGEDISK (get_param(MODE_CHANGEDISK))
#define IS_UPDATEMODULES (get_param(MODE_UPDATEMODULES))
void fatal_error(char *msg) __attribute__ ((noreturn));
void stg1_error_message(char *msg, ...) __attribute__ ((format (printf, 1, 2)));
void stg1_info_message(char *msg, ...) __attribute__ ((format (printf, 1, 2)));
#endif

361
stdio-frontend.c Normal file
View File

@ -0,0 +1,361 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Each different frontend must implement all functions defined in frontend.h
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <termios.h>
#include "frontend.h"
void init_frontend(char * welcome_msg)
{
printf(welcome_msg);
}
void finish_frontend(void)
{
}
static void get_any_response(void)
{
unsigned char t;
printf("\n\t(press <enter> to proceed)");
fflush(stdout);
read(0, &t, 1);
fcntl(0, F_SETFL, O_NONBLOCK);
while (read(0, &t, 1) > 0);
fcntl(0, F_SETFL, 0);
}
static int get_int_response(void)
{
char s[50];
int j = 0, i = 0; /* (0) tied to Cancel */
fflush(stdout);
read(0, &(s[i++]), 1);
fcntl(0, F_SETFL, O_NONBLOCK);
do {
int v = s[i-1];
if (v >= '0' && v <= '9')
j = j*10 + (v - '0');
} while (read(0, &(s[i++]), 1) > 0 && i < sizeof(s));
fcntl(0, F_SETFL, 0);
return j;
}
static char * get_string_response(char * initial_string)
{
/* I won't use a scanf/%s since I also want the null string to be accepted -- also, I want the initial_string */
char s[500];
int i = 0;
char buf[10];
int b_index = 0;
char b;
struct termios t;
memset(s, '\0', sizeof(s));
if (initial_string) {
printf(initial_string);
strcpy(s, initial_string);
i = strlen(s);
}
/* from ncurses/tinfo/lib_raw.c:(cbreak) */
tcgetattr(0, &t);
t.c_lflag &= ~ICANON;
t.c_lflag |= ISIG;
t.c_lflag &= ~ECHO;
t.c_iflag &= ~ICRNL;
t.c_cc[VMIN] = 1;
t.c_cc[VTIME] = 0;
tcsetattr(0, TCSADRAIN, &t);
fflush(stdout);
fcntl(0, F_SETFL, O_NONBLOCK);
while (1) {
if (read(0, &b, 1) > 0) {
if (b_index == 1) {
if (b == 91) {
buf[b_index] = b;
b_index++;
continue;
}
else
b_index = 0;
}
if (b_index == 2) {
if (b == 67) {
if (s[i] != '\0') {
printf("\033[C");
i++;
}
}
if (b == 68) {
if (i > 0) {
printf("\033[D");
i--;
}
}
b_index = 0;
continue;
}
if (b == 13)
break;
if (b == 127) {
if (i > 0) {
printf("\033[D");
printf(" ");
printf("\033[D");
if (s[i] == '\0')
s[i-1] = '\0';
else
s[i-1] = ' ';
i--;
}
} else if (b == 27) {
buf[b_index] = b;
b_index++;
} else {
printf("%c", b);
s[i] = b;
i++;
}
}
}
t.c_lflag |= ICANON;
t.c_lflag |= ECHO;
t.c_iflag |= ICRNL;
tcsetattr(0, TCSADRAIN, &t);
fcntl(0, F_SETFL, 0);
printf("\n");
return strdup(s);
}
static void blocking_msg(char *type, char *fmt, va_list ap)
{
printf(type);
vprintf(fmt, ap);
get_any_response();
}
void verror_message(char *msg, va_list ap)
{
blocking_msg("> Error! ", msg, ap);
}
void vinfo_message(char *msg, va_list ap)
{
blocking_msg("> Notice: ", msg, ap);
}
void vwait_message(char *msg, va_list ap)
{
printf("Please wait: ");
vprintf(msg, ap);
fflush(stdout);
}
void remove_wait_message(void)
{
printf("\n");
}
static int size_progress;
static int actually_drawn;
#define PROGRESS_SIZE 45
void init_progression(char *msg, int size)
{
int i;
size_progress = size;
printf("%s ", msg);
if (size) {
actually_drawn = 0;
for (i=0; i<PROGRESS_SIZE; i++)
printf(".");
printf("]\033[G%s [", msg); /* only works on ANSI-compatibles */
fflush(stdout);
} else
printf("\n");
}
void update_progression(int current_size)
{
if (size_progress) {
if (current_size > size_progress)
current_size = size_progress;
while ((int)((current_size*PROGRESS_SIZE)/size_progress) > actually_drawn) {
printf("*");
actually_drawn++;
}
} else
printf("\033[GStatus: [%8d] bytes loaded...", current_size);
fflush(stdout);
}
void end_progression(void)
{
if (size_progress) {
update_progression(size_progress);
printf("]\n");
} else
printf(" done.\n");
}
enum return_type ask_from_list_comments(char *msg, char ** elems, char ** elems_comments, char ** choice)
{
int justify_number = 1;
void print_choice_number(int i) {
char tmp[500];
snprintf(tmp, sizeof(tmp), "[%%%dd]", justify_number);
printf(tmp, i);
}
char ** sav_elems = elems;
int i = 1;
int j = 0;
while (elems && *elems) {
elems++;
i++;
}
if (i >= 10)
justify_number = 2;
elems = sav_elems;
i = 1;
printf("> %s\n", msg);
print_choice_number(0);
printf(" Cancel");
while (elems && *elems) {
if (elems_comments && *elems_comments) {
printf("\n");
print_choice_number(i);
printf(" %s (%s)", *elems, *elems_comments);
j = 0;
} else {
if (j == 0)
printf("\n");
print_choice_number(i);
printf(" %-14s ", *elems);
j++;
}
if (j == 4)
j = 0;
if (elems_comments)
elems_comments++;
i++;
elems++;
}
printf("\n? ");
j = get_int_response();
if (j == 0)
return RETURN_BACK;
if (j >= 1 && j <= i) {
*choice = strdup(sav_elems[j-1]);
return RETURN_OK;
}
return RETURN_ERROR;
}
enum return_type ask_from_list(char *msg, char ** elems, char ** choice)
{
return ask_from_list_comments(msg, elems, NULL, choice);
}
enum return_type ask_yes_no(char *msg)
{
int j;
printf("> %s\n[0] Yes [1] No [2] Back\n? ", msg);
j = get_int_response();
if (j == 0)
return RETURN_OK;
else if (j == 2)
return RETURN_BACK;
else return RETURN_ERROR;
}
enum return_type ask_from_entries(char *msg, char ** questions, char *** answers, int entry_size, void (*callback_func)(char ** strings))
{
int j, i = 0;
char ** already_answers = NULL;
printf("> %s\n", msg);
while (questions && *questions) {
printf("(%c) %s\n", i + 'a', *questions);
i++;
questions++;
}
if (*answers == NULL)
*answers = (char **) malloc(sizeof(char *) * i);
else
already_answers = *answers;
while (1) {
int r;
for (j = 0 ; j < i ; j++) {
printf("(%c) ? ", j + 'a');
if (already_answers && *already_answers) {
(*answers)[j] = get_string_response(*already_answers);
already_answers++;
} else
(*answers)[j] = get_string_response(NULL);
}
printf("[0] Cancel [1] Accept [2] Re-enter answers\n? ");
r = get_int_response();
if (r == 0)
return RETURN_BACK;
if (r == 1)
return RETURN_OK;
}
}

435
tools.c Normal file
View File

@ -0,0 +1,435 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <bzlib.h>
#include <sys/mount.h>
#include <sys/poll.h>
#include "stage1.h"
#include "log.h"
#include "mount.h"
#include "frontend.h"
#include "automatic.h"
#include "tools.h"
static struct param_elem params[50];
static int param_number = 0;
void process_cmdline(void)
{
char buf[512];
int fd, size, i;
log_message("opening /proc/cmdline... ");
if ((fd = open("/proc/cmdline", O_RDONLY)) == -1)
fatal_error("could not open /proc/cmdline");
size = read(fd, buf, sizeof(buf));
buf[size-1] = '\0'; // -1 to eat the \n
close(fd);
log_message("\t%s", buf);
i = 0;
while (buf[i] != '\0') {
char *name, *value = NULL;
int j = i;
while (buf[i] != ' ' && buf[i] != '=' && buf[i] != '\0')
i++;
if (i == j) {
i++;
continue;
}
name = memdup(&buf[j], i-j + 1);
name[i-j] = '\0';
if (buf[i] == '=') {
int k = i+1;
i++;
while (buf[i] != ' ' && buf[i] != '\0')
i++;
value = memdup(&buf[k], i-k + 1);
value[i-k] = '\0';
}
params[param_number].name = name;
params[param_number].value = value;
param_number++;
if (!strcmp(name, "expert")) set_param(MODE_EXPERT);
if (!strcmp(name, "changedisk")) set_param(MODE_CHANGEDISK);
if (!strcmp(name, "updatemodules")) set_param(MODE_UPDATEMODULES);
if (!strcmp(name, "rescue")) set_param(MODE_RESCUE);
if (!strcmp(name, "special_stage2")) set_param(MODE_SPECIAL_STAGE2);
if (!strcmp(name, "lowmem")) set_param(MODE_LOWMEM);
if (!strcmp(name, "automatic")) {
set_param(MODE_AUTOMATIC);
grab_automatic_params(value);
}
if (buf[i] == '\0')
break;
i++;
}
log_message("\tgot %d args", param_number);
}
int stage1_mode = 0;
int get_param(int i)
{
#ifdef SPAWN_INTERACTIVE
static int fd = 0;
char buf[5000];
char * ptr;
int nb;
if (fd <= 0) {
fd = open(interactive_fifo, O_RDONLY);
if (fd == -1)
return (stage1_mode & i);
fcntl(fd, F_SETFL, O_NONBLOCK);
}
if (fd > 0) {
if ((nb = read(fd, buf, sizeof(buf))) > 0) {
buf[nb] = '\0';
ptr = buf;
while ((ptr = strstr(ptr, "+ "))) {
if (!strncmp(ptr+2, "expert", 6)) set_param(MODE_EXPERT);
if (!strncmp(ptr+2, "rescue", 6)) set_param(MODE_RESCUE);
ptr++;
}
ptr = buf;
while ((ptr = strstr(ptr, "- "))) {
if (!strncmp(ptr+2, "expert", 6)) unset_param(MODE_EXPERT);
if (!strncmp(ptr+2, "rescue", 6)) unset_param(MODE_RESCUE);
ptr++;
}
}
}
#endif
return (stage1_mode & i);
}
char * get_param_valued(char *param_name)
{
int i;
for (i = 0; i < param_number ; i++)
if (!strcmp(params[i].name, param_name))
return params[i].value;
return NULL;
}
void set_param_valued(char *param_name, char *param_value)
{
params[param_number].name = param_name;
params[param_number].value = param_value;
param_number++;
}
void set_param(int i)
{
stage1_mode |= i;
if (i == MODE_RESCUE) {
set_param_valued("special_stage2", "rescue");
set_param(MODE_SPECIAL_STAGE2);
}
}
void unset_param(int i)
{
stage1_mode &= ~i;
}
// warning, many things rely on the fact that:
// - when failing it returns 0
// - it stops on first non-digit char
int charstar_to_int(char * s)
{
int number = 0;
while (*s && isdigit(*s)) {
number = (number * 10) + (*s - '0');
s++;
}
return number;
}
int total_memory(void)
{
int value;
struct stat statr;
if (stat("/proc/kcore", &statr))
return 0;
/* drakx powered: use /proc/kcore and rounds every 4 Mbytes */
value = 4 * ((int)((float)statr.st_size / 1024 / 1024 / 4 + 0.5));
log_message("Total Memory: %d Mbytes", value);
return value;
}
int ramdisk_possible(void)
{
if (total_memory() > (IS_RESCUE ? MEM_LIMIT_RESCUE : MEM_LIMIT_RAMDISK))
return 1;
else {
log_message("warning, ramdisk is not possible due to low mem!");
return 0;
}
}
static void save_stuff_for_rescue(void)
{
void save_this_file(char * file) {
char buf[5000];
int fd_r, fd_w, i;
char location[100];
if ((fd_r = open(file, O_RDONLY)) < 0) {
log_message("can't open %s for read", file);
return;
}
strcpy(location, STAGE2_LOCATION);
strcat(location, file);
if ((fd_w = open(location, O_WRONLY)) < 0) {
log_message("can't open %s for write", location);
close(fd_r);
return;
}
if ((i = read(fd_r, buf, sizeof(buf))) <= 0) {
log_message("can't read from %s", file);
close(fd_r); close(fd_w);
return;
}
if (write(fd_w, buf, i) != i)
log_message("can't write %d bytes to %s", i, location);
close(fd_r); close(fd_w);
log_message("saved file %s for rescue (%d bytes)", file, i);
}
save_this_file("/etc/resolv.conf");
}
enum return_type load_ramdisk_fd(int ramdisk_fd, int size)
{
BZFILE * st2;
char * ramdisk = "/dev/ram3"; /* warning, verify that this file exists in the initrd, and that root=/dev/ram3 is actually passed to the kernel at boot time */
int ram_fd;
char buffer[32768];
int z_errnum;
char * wait_msg = "Loading program into memory...";
int bytes_read = 0;
int actually;
int seems_ok = 0;
st2 = BZ2_bzdopen(ramdisk_fd, "r");
if (!st2) {
log_message("Opening compressed ramdisk: %s", BZ2_bzerror(st2, &z_errnum));
stg1_error_message("Could not open compressed ramdisk file.");
return RETURN_ERROR;
}
ram_fd = open(ramdisk, O_WRONLY);
if (ram_fd == -1) {
log_perror(ramdisk);
stg1_error_message("Could not open ramdisk device file.");
return RETURN_ERROR;
}
init_progression(wait_msg, size);
while ((actually = BZ2_bzread(st2, buffer, sizeof(buffer))) > 0) {
seems_ok = 1;
if (write(ram_fd, buffer, actually) != actually) {
log_perror("writing ramdisk");
remove_wait_message();
return RETURN_ERROR;
}
update_progression((int)((bytes_read += actually) / RAMDISK_COMPRESSION_RATIO));
}
if (!seems_ok) {
log_message("reading compressed ramdisk: %s", BZ2_bzerror(st2, &z_errnum));
BZ2_bzclose(st2); /* opened by gzdopen, but also closes the associated fd */
close(ram_fd);
remove_wait_message();
stg1_error_message("Could not uncompress second stage ramdisk. "
"This is probably an hardware error while reading the data. "
"(this may be caused by a hardware failure or a Linux kernel bug)");
return RETURN_ERROR;
}
end_progression();
BZ2_bzclose(st2); /* opened by gzdopen, but also closes the associated fd */
close(ram_fd);
if (my_mount(ramdisk, STAGE2_LOCATION, "ext2", 1))
return RETURN_ERROR;
set_param(MODE_RAMDISK);
if (IS_RESCUE) {
save_stuff_for_rescue();
if (umount(STAGE2_LOCATION)) {
log_perror(ramdisk);
return RETURN_ERROR;
}
return RETURN_OK; /* fucksike, I lost several hours wondering why the kernel won't see the rescue if it is alreay mounted */
}
return RETURN_OK;
}
char * get_ramdisk_realname(void)
{
char img_name[500];
char * stg2_name = get_param_valued("special_stage2");
char * begin_img = RAMDISK_LOCATION;
char * end_img = "_stage2.bz2";
if (!stg2_name)
stg2_name = "mdkinst";
if (IS_RESCUE)
stg2_name = "rescue";
strcpy(img_name, begin_img);
strcat(img_name, stg2_name);
strcat(img_name, end_img);
return strdup(img_name);
}
enum return_type load_ramdisk(void)
{
int st2_fd;
struct stat statr;
char img_name[500];
strcpy(img_name, IMAGE_LOCATION);
strcat(img_name, get_ramdisk_realname());
log_message("trying to load %s as a ramdisk", img_name);
st2_fd = open(img_name, O_RDONLY); /* to be able to see the progression */
if (st2_fd == -1) {
log_message("open ramdisk file (%s) failed", img_name);
stg1_error_message("Could not open compressed ramdisk file (%s).", img_name);
return RETURN_ERROR;
}
if (stat(img_name, &statr))
return RETURN_ERROR;
else
return load_ramdisk_fd(st2_fd, statr.st_size);
}
/* pixel's */
void * memdup(void *src, size_t size)
{
void * r;
r = malloc(size);
memcpy(r, src, size);
return r;
}
static char ** my_env = NULL;
static int env_size = 0;
void handle_env(char ** env)
{
char ** ptr = env;
while (ptr && *ptr) {
ptr++;
env_size++;
}
my_env = malloc(sizeof(char *) * 100);
memcpy(my_env, env, sizeof(char *) * (env_size+1));
}
char ** grab_env(void) {
return my_env;
}
void add_to_env(char * name, char * value)
{
char tmp[500];
sprintf(tmp, "%s=%s", name, value);
my_env[env_size] = strdup(tmp);
env_size++;
my_env[env_size] = NULL;
}
char ** list_directory(char * direct)
{
char * tmp[50000]; /* in /dev there can be many many files.. */
int i = 0;
struct dirent *ep;
DIR *dp = opendir(direct);
while (dp && (ep = readdir(dp))) {
if (strcmp(ep->d_name, ".") && strcmp(ep->d_name, "..")) {
tmp[i] = strdup(ep->d_name);
i++;
}
}
if (dp)
closedir(dp);
tmp[i] = NULL;
return memdup(tmp, sizeof(char*) * (i+1));
}
int string_array_length(char ** a)
{
int i = 0;
if (!a)
return -1;
while (a && *a) {
a++;
i++;
}
return i;
}

53
tools.h Normal file
View File

@ -0,0 +1,53 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan (ewt@redhat.com)
*
* Copyright 1996 Red Hat Software
*
*/
#ifndef _TOOLS_H_
#define _TOOLS_H_
#include <stdlib.h>
void process_cmdline(void);
int get_param(int i);
void set_param(int i);
void unset_param(int i);
int charstar_to_int(char * s);
int total_memory(void);
int ramdisk_possible(void);
char * get_ramdisk_realname(void);
enum return_type load_ramdisk(void);
enum return_type load_ramdisk_fd(int ramdisk_fd, int size);
void * memdup(void *src, size_t size);
void add_to_env(char * name, char * value);
void handle_env(char ** env);
char ** grab_env(void);
char ** list_directory(char * direct);
int string_array_length(char ** a);
struct param_elem
{
char * name;
char * value;
};
#define ptr_begins_static_str(pointer,static_str) (!strncmp(pointer,static_str,sizeof(static_str)-1))
#define streq !strcmp
#endif

501
url.c Normal file
View File

@ -0,0 +1,501 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan <ewt@redhat.com> and Matt Wilson <msw@redhat.com>
*
* Copyright 1999 Red Hat, Inc.
*
*/
#include <alloca.h>
// #include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in_systm.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// #include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/poll.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include "dns.h"
#include "log.h"
#include "tools.h"
#include "url.h"
#define TIMEOUT_SECS 60
#define BUFFER_SIZE 4096
static int ftp_check_response(int sock, char ** str)
{
static char buf[BUFFER_SIZE + 1];
int bufLength = 0;
struct pollfd polls;
char * chptr, * start;
int bytesRead, rc = 0;
int doesContinue = 1;
char errorCode[4];
errorCode[0] = '\0';
do {
polls.fd = sock;
polls.events = POLLIN;
if (poll(&polls, 1, TIMEOUT_SECS*1000) != 1)
return FTPERR_BAD_SERVER_RESPONSE;
bytesRead = read(sock, buf + bufLength, sizeof(buf) - bufLength - 1);
bufLength += bytesRead;
buf[bufLength] = '\0';
/* divide the response into lines, checking each one to see if
we are finished or need to continue */
start = chptr = buf;
do {
while (*chptr != '\n' && *chptr) chptr++;
if (*chptr == '\n') {
*chptr = '\0';
if (*(chptr - 1) == '\r') *(chptr - 1) = '\0';
if (str) *str = start;
if (errorCode[0]) {
if (!strncmp(start, errorCode, 3) && start[3] == ' ')
doesContinue = 0;
} else {
strncpy(errorCode, start, 3);
errorCode[3] = '\0';
if (start[3] != '-') {
doesContinue = 0;
}
}
start = chptr + 1;
chptr++;
} else {
chptr++;
}
} while (*chptr);
if (doesContinue && chptr > start) {
memcpy(buf, start, chptr - start - 1);
bufLength = chptr - start - 1;
} else {
bufLength = 0;
}
} while (doesContinue);
if (*errorCode == '4' || *errorCode == '5') {
if (!strncmp(errorCode, "550", 3)) {
return FTPERR_FILE_NOT_FOUND;
}
return FTPERR_BAD_SERVER_RESPONSE;
}
if (rc) return rc;
return 0;
}
static int ftp_command(int sock, char * command, char * param)
{
char buf[500];
int rc;
strcpy(buf, command);
if (param) {
strcat(buf, " ");
strcat(buf, param);
}
strcat(buf, "\r\n");
if (write(sock, buf, strlen(buf)) != strlen(buf)) {
return FTPERR_SERVER_IO_ERROR;
}
if ((rc = ftp_check_response(sock, NULL)))
return rc;
return 0;
}
static int get_host_address(char * host, struct in_addr * address)
{
if (isdigit(host[0])) {
if (!inet_aton(host, address)) {
return FTPERR_BAD_HOST_ADDR;
}
} else {
if (mygethostbyname(host, address))
return FTPERR_BAD_HOSTNAME;
}
return 0;
}
int ftp_open_connection(char * host, char * name, char * password, char * proxy)
{
int sock;
struct in_addr serverAddress;
struct sockaddr_in destPort;
char * buf;
int rc;
int port = 21;
if (!strcmp(name, "")) {
name = "anonymous";
password = "-drakx@";
}
if (strcmp(proxy, "")) {
buf = alloca(strlen(name) + strlen(host) + 5);
sprintf(buf, "%s@%s", name, host);
name = buf;
host = proxy;
}
if ((rc = get_host_address(host, &serverAddress))) return rc;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (sock < 0) {
return FTPERR_FAILED_CONNECT;
}
destPort.sin_family = AF_INET;
destPort.sin_port = htons(port);
destPort.sin_addr = serverAddress;
if (connect(sock, (struct sockaddr *) &destPort, sizeof(destPort))) {
close(sock);
return FTPERR_FAILED_CONNECT;
}
/* ftpCheckResponse() assumes the socket is nonblocking */
if (fcntl(sock, F_SETFL, O_NONBLOCK)) {
close(sock);
return FTPERR_FAILED_CONNECT;
}
if ((rc = ftp_check_response(sock, NULL))) {
return rc;
}
if ((rc = ftp_command(sock, "USER", name))) {
close(sock);
return rc;
}
if ((rc = ftp_command(sock, "PASS", password))) {
close(sock);
return rc;
}
if ((rc = ftp_command(sock, "TYPE", "I"))) {
close(sock);
return rc;
}
return sock;
}
int ftp_data_command(int sock, char * command, char * param)
{
int dataSocket;
struct sockaddr_in dataAddress;
int i, j;
char * passReply;
char * chptr;
char retrCommand[500];
int rc;
if (write(sock, "PASV\r\n", 6) != 6) {
return FTPERR_SERVER_IO_ERROR;
}
if ((rc = ftp_check_response(sock, &passReply)))
return FTPERR_PASSIVE_ERROR;
chptr = passReply;
while (*chptr && *chptr != '(') chptr++;
if (*chptr != '(') return FTPERR_PASSIVE_ERROR;
chptr++;
passReply = chptr;
while (*chptr && *chptr != ')') chptr++;
if (*chptr != ')') return FTPERR_PASSIVE_ERROR;
*chptr-- = '\0';
while (*chptr && *chptr != ',') chptr--;
if (*chptr != ',') return FTPERR_PASSIVE_ERROR;
chptr--;
while (*chptr && *chptr != ',') chptr--;
if (*chptr != ',') return FTPERR_PASSIVE_ERROR;
*chptr++ = '\0';
/* now passReply points to the IP portion, and chptr points to the
port number portion */
dataAddress.sin_family = AF_INET;
if (sscanf(chptr, "%d,%d", &i, &j) != 2) {
return FTPERR_PASSIVE_ERROR;
}
dataAddress.sin_port = htons((i << 8) + j);
chptr = passReply;
while (*chptr++) {
if (*chptr == ',') *chptr = '.';
}
if (!inet_aton(passReply, &dataAddress.sin_addr))
return FTPERR_PASSIVE_ERROR;
dataSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (dataSocket < 0) {
return FTPERR_FAILED_CONNECT;
}
if (!param)
sprintf(retrCommand, "%s\r\n", command);
else
sprintf(retrCommand, "%s %s\r\n", command, param);
i = strlen(retrCommand);
if (write(sock, retrCommand, i) != i) {
return FTPERR_SERVER_IO_ERROR;
}
if (connect(dataSocket, (struct sockaddr *) &dataAddress,
sizeof(dataAddress))) {
close(dataSocket);
return FTPERR_FAILED_DATA_CONNECT;
}
if ((rc = ftp_check_response(sock, NULL))) {
close(dataSocket);
return rc;
}
return dataSocket;
}
static int ftp_get_filesize(int sock, char * remotename)
{
int size = 0;
char buf[2000];
char file[500];
char * ptr;
int fd, rc, tot;
int i;
strcpy(buf, remotename);
ptr = strrchr(buf, '/');
if (!*ptr)
return -1;
*ptr = '\0';
strcpy(file, ptr+1);
if ((rc = ftp_command(sock, "CWD", buf))) {
return -1;
}
fd = ftp_data_command(sock, "LIST", NULL);
if (fd <= 0) {
close(sock);
return -1;
}
ptr = buf;
while ((tot = read(fd, ptr, sizeof(buf) - (ptr - buf))) != 0)
ptr += tot;
*ptr = '\0';
close(fd);
if (!(ptr = strstr(buf, file))) {
log_message("FTP/get_filesize: Bad mood, directory does not contain searched file (%s)", file);
if (ftp_end_data_command(sock))
close(sock);
return -1;
}
for (i=0; i<4; i++) {
while (*ptr && *ptr != ' ')
ptr--;
while (*ptr && *ptr == ' ')
ptr--;
}
while (*ptr && *ptr != ' ')
ptr--;
if (ptr)
size = charstar_to_int(ptr+1);
else
size = 0;
if (ftp_end_data_command(sock)) {
close(sock);
return -1;
}
return size;
}
int ftp_start_download(int sock, char * remotename, int * size)
{
if ((*size = ftp_get_filesize(sock, remotename)) == -1) {
log_message("FTP: could not get filesize (trying to continue)");
*size = 0;
}
return ftp_data_command(sock, "RETR", remotename);
}
int ftp_end_data_command(int sock)
{
if (ftp_check_response(sock, NULL))
return FTPERR_BAD_SERVER_RESPONSE;
return 0;
}
int http_download_file(char * hostname, char * remotename, int * size)
{
char * buf;
char headers[4096];
char * nextChar = headers;
int checkedCode;
struct in_addr serverAddress;
struct pollfd polls;
int sock;
int rc;
struct sockaddr_in destPort;
char * header_content_length = "Content-Length: ";
if ((rc = get_host_address(hostname, &serverAddress))) return rc;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (sock < 0) {
return FTPERR_FAILED_CONNECT;
}
destPort.sin_family = AF_INET;
destPort.sin_port = htons(80);
destPort.sin_addr = serverAddress;
if (connect(sock, (struct sockaddr *) &destPort, sizeof(destPort))) {
close(sock);
return FTPERR_FAILED_CONNECT;
}
buf = alloca(strlen(remotename) + 20);
sprintf(buf, "GET %s HTTP/0.9\r\n\r\n", remotename);
write(sock, buf, strlen(buf));
/* This is fun; read the response a character at a time until we:
1) Get our first \r\n; which lets us check the return code
2) Get a \r\n\r\n, which means we're done */
*nextChar = '\0';
checkedCode = 0;
while (!strstr(headers, "\r\n\r\n")) {
polls.fd = sock;
polls.events = POLLIN;
rc = poll(&polls, 1, TIMEOUT_SECS*1000);
if (rc == 0) {
close(sock);
return FTPERR_SERVER_TIMEOUT;
} else if (rc < 0) {
close(sock);
return FTPERR_SERVER_IO_ERROR;
}
if (read(sock, nextChar, 1) != 1) {
close(sock);
return FTPERR_SERVER_IO_ERROR;
}
nextChar++;
*nextChar = '\0';
if (nextChar - headers == sizeof(headers)) {
close(sock);
return FTPERR_SERVER_IO_ERROR;
}
if (!checkedCode && strstr(headers, "\r\n")) {
char * start, * end;
checkedCode = 1;
start = headers;
while (!isspace(*start) && *start) start++;
if (!*start) {
close(sock);
return FTPERR_SERVER_IO_ERROR;
}
start++;
end = start;
while (!isspace(*end) && *end) end++;
if (!*end) {
close(sock);
return FTPERR_SERVER_IO_ERROR;
}
*end = '\0';
if (!strcmp(start, "404")) {
close(sock);
return FTPERR_FILE_NOT_FOUND;
} else if (strcmp(start, "200")) {
close(sock);
return FTPERR_BAD_SERVER_RESPONSE;
}
*end = ' ';
}
}
if ((buf = strstr(headers, header_content_length)))
*size = charstar_to_int(buf + strlen(header_content_length));
else
*size = 0;
return sock;
}

44
url.h Normal file
View File

@ -0,0 +1,44 @@
/*
* Guillaume Cottenceau (gc@mandrakesoft.com)
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* 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.
*
*/
/*
* Portions from Erik Troan <ewt@redhat.com> and Matt Wilson <msw@redhat.com>
*
* Copyright 1999 Red Hat, Inc.
*
*/
#ifndef _URL_H_
#define _URL_H_
int ftp_open_connection(char * host, char * name, char * password, char * proxy);
int ftp_start_download(int sock, char * remotename, int * size);
int ftp_end_data_command(int sock);
int http_download_file(char * hostname, char * remotename, int * size);
#define FTPERR_BAD_SERVER_RESPONSE -1
#define FTPERR_SERVER_IO_ERROR -2
#define FTPERR_SERVER_TIMEOUT -3
#define FTPERR_BAD_HOST_ADDR -4
#define FTPERR_BAD_HOSTNAME -5
#define FTPERR_FAILED_CONNECT -6
#define FTPERR_FILE_IO_ERROR -7
#define FTPERR_PASSIVE_ERROR -8
#define FTPERR_FAILED_DATA_CONNECT -9
#define FTPERR_FILE_NOT_FOUND -10
#define FTPERR_UNKNOWN -100
#endif

1
usb-resource/.cvsignore Normal file
View File

@ -0,0 +1 @@
usb-ids.h

25
usb-resource/Makefile Normal file
View File

@ -0,0 +1,25 @@
#******************************************************************************
#
# $Id$
#
# Guillaume Cottenceau (gc@mandrakesoft.com)
#
# Copyright 2000 MandrakeSoft
#
# This software may be freely redistributed under the terms of the GNU
# 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.
#
#*****************************************************************************
all: usb-ids.h
usb-ids.h: /usr/share/ldetect-lst/usbtable update-usb-ids.pl
perl update-usb-ids.pl > $@ || rm -f $@
clean:
rm -f usb-ids.h

73
usb-resource/update-usb-ids.pl Executable file
View File

@ -0,0 +1,73 @@
#!/usr/bin/perl
sub cat_ { local *F; open F, $_[0] or $_[1] ? die "cat of file $_[0] failed: $!\n" : return; my @l = <F>; wantarray ? @l : join '', @l }
-x "../mar/mar" or die "\t*FAILED* Sorry, need ../mar/mar binary\n";
my @usbtable_tmp = cat_("/usr/share/ldetect-lst/usbtable");
my @usbtable;
foreach (@usbtable_tmp) {
next if /\s*#/;
/\s*(\S+)\s+(\S+)\s+"(\S+)"\s+"([^"]*)"/ or next;
push @usbtable, { 'vendor' => $1, 'id' => $2, 'module' => $3, 'description' => $4 };
}
print '
struct usb_module_map {
unsigned short vendor; /* vendor */
unsigned short id; /* device */
const char *name; /* human readable name */
const char *module; /* module to load */
};
';
print "#ifdef ENABLE_USB
struct pci_module_map usb_pci_ids[] = {
";
require '/usr/bin/merge2pcitable.pl';
my $drivers = read_pcitable("/usr/share/ldetect-lst/pcitable");
while (my ($k, $v) = each %$drivers) {
$v->[0] =~ /^usb-/ or next;
$k =~ /^(....)(....)/;
printf qq|\t{ 0x%s, 0x%s, "", "%s" },\n|,
$1, $2, $v->[0];
}
print "};
int usb_num_ids=sizeof(usb_pci_ids)/sizeof(struct pci_module_map);
#endif
";
my @t = ('usbnet');
foreach $type (@t) {
my $modulez;
foreach (glob("../../all.modules/*/${type}_modules.mar")) {
-f $_ or die "\t*FAILED* Sorry, need $_ mar file\n";
push @$modulez, (`../mar/mar -l $_`);
}
print "#ifdef ENABLE_".uc($type)."
struct usb_module_map ${type}_usb_ids[] = {
";
foreach my $usbentry (@usbtable) {
grep(/^\t$usbentry->{'module'}\.o\s/, @$modulez) or next;
printf qq|\t{ %s, %s, "%s", "%s" },\n|,
$usbentry->{'vendor'}, $usbentry->{'id'}, $usbentry->{'description'}, $usbentry->{'module'};
}
print "};
int ${type}_usb_num_ids=sizeof(${type}_usb_ids)/sizeof(struct usb_module_map);
#endif
";
}