Initial revision
This commit is contained in:
commit
46438969c6
11
.cvsignore
Normal file
11
.cvsignore
Normal 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
24
MANIFEST.doc
Normal 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
265
Makefile
Normal 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
59
Makefile.common
Normal 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
30
Makefile.mkinitrd_helper
Normal 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
|
172
adsl.c
Normal file
172
adsl.c
Normal 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
34
adsl.h
Normal 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
162
automatic.c
Normal 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
32
automatic.h
Normal 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
184
cdrom.c
Normal 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
29
cdrom.h
Normal 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
48
config-stage1.h
Normal 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
48
config-stage1.h-master
Normal 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
615
dhcp.c
Normal 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
34
dhcp.h
Normal 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
342
disk.c
Normal 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
27
disk.h
Normal 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
213
dns.c
Normal 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
30
dns.h
Normal 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
31
doc/HACKING
Normal 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
185
doc/README
Normal 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
80
doc/TECH-INFOS
Normal 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
71
doc/UPDATEMODULES
Normal 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
50
doc/WHY-DIETLIBC
Normal 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]
|
69
doc/documented..frontend.h
Normal file
69
doc/documented..frontend.h
Normal 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
43
frontend-common.c
Normal 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
50
frontend.h
Normal 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
44
init-libc-headers.h
Normal 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
497
init.c
Normal 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
20
insmod.h
Normal 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
143
log
Normal 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
85
log.c
Normal 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
34
log.h
Normal 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
171
lomount.c
Normal 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
21
lomount.h
Normal 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
251
minilibc.c
Normal 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
144
minilibc.h
Normal 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
46
mkinitrd_helper/Makefile
Normal 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) $@
|
308
mkinitrd_helper/mkinitrd_helper.c
Normal file
308
mkinitrd_helper/mkinitrd_helper.c
Normal 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
446
modules.c
Normal 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
35
modules.h
Normal 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
66
modules_descr.h
Normal 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
188
mount.c
Normal 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
35
mount.h
Normal 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
208
mount_rpcgen.h
Normal 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
830
network.c
Normal 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
61
network.h
Normal 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
392
newt-frontend.c
Normal 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
54
nfs_mount4.h
Normal 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
739
nfsmount.c
Normal 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 Mi¶kiewicz <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
331
nfsmount.h
Normal 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
1
pci-resource/.cvsignore
Normal file
@ -0,0 +1 @@
|
||||
pci-ids.h
|
25
pci-resource/Makefile
Normal file
25
pci-resource/Makefile
Normal 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
74
pci-resource/update-pci-ids.pl
Executable 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
48
pcmcia/Makefile
Normal 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
195
pcmcia/bulkmem.h
Normal 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
157
pcmcia/bus_ops.h
Normal 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
1471
pcmcia/cardmgr.c
Normal file
File diff suppressed because it is too large
Load Diff
113
pcmcia/cardmgr.h
Normal file
113
pcmcia/cardmgr.h
Normal 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
182
pcmcia/cirrus.h
Normal 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
138
pcmcia/ciscode.h
Normal 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
135
pcmcia/cisreg.h
Normal 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
604
pcmcia/cistpl.h
Normal 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
59
pcmcia/config.h
Normal 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
441
pcmcia/cs.h
Normal 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
70
pcmcia/cs_types.h
Normal 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
73
pcmcia/driver_ops.h
Normal 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
148
pcmcia/ds.h
Normal 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
154
pcmcia/i82365.h
Normal 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
2062
pcmcia/lex_config.c
Normal file
File diff suppressed because it is too large
Load Diff
269
pcmcia/lex_config.l
Normal file
269
pcmcia/lex_config.l
Normal 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
21
pcmcia/pcmcia.h
Normal 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
419
pcmcia/pcmcia_probe.c
Normal 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
266
pcmcia/tcic.h
Normal 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
13
pcmcia/version.h
Normal 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
112
pcmcia/vg468.h
Normal 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
1148
pcmcia/yacc_config.c
Normal file
File diff suppressed because it is too large
Load Diff
42
pcmcia/yacc_config.h
Normal file
42
pcmcia/yacc_config.h
Normal 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
553
pcmcia/yacc_config.y
Normal 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
46
pcmcia_config.patch
Normal 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
658
probing.c
Normal 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
36
probing.h
Normal 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
|
BIN
stage1-data/stage1-with-busybox.tar.bz2
Normal file
BIN
stage1-data/stage1-with-busybox.tar.bz2
Normal file
Binary file not shown.
BIN
stage1-data/stage1-with-sash.tar.bz2
Normal file
BIN
stage1-data/stage1-with-sash.tar.bz2
Normal file
Binary file not shown.
BIN
stage1-data/stage1.tar.bz2
Normal file
BIN
stage1-data/stage1.tar.bz2
Normal file
Binary file not shown.
439
stage1.c
Normal file
439
stage1.c
Normal 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
60
stage1.h
Normal 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
361
stdio-frontend.c
Normal 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
435
tools.c
Normal 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
53
tools.h
Normal 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
501
url.c
Normal 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
44
url.h
Normal 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
1
usb-resource/.cvsignore
Normal file
@ -0,0 +1 @@
|
||||
usb-ids.h
|
25
usb-resource/Makefile
Normal file
25
usb-resource/Makefile
Normal 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
73
usb-resource/update-usb-ids.pl
Executable 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
|
||||
";
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user