massive change caused by udev use in initramfs:

- added udevd, udevtrigger & udevsettle spawning from init,
reproducing nead same logic, found in initrd, created by
/sbin/mkinitd
- lots of obsolete by this change stuff removed
- use external /sbin/modprobe form klibc utils
in places, where manual module loading still needed
- pack unchangeable part of initramfs into `initfs'
file (gzipped cpio archive), which may be concatenated later
with other parts (especially kernel modules) to form
actual initramfs image.
This commit is contained in:
Sergey Bolshakov 2008-03-01 22:02:06 +03:00
parent 85b34d353b
commit 0a6af0fb35
22 changed files with 361 additions and 1628 deletions

View File

@ -1 +1 @@
tar.bz2: . name=propagator-@version@ base= tar: . name=@name@-@version@-@release@ base=@name@-@version@

159
Makefile
View File

@ -1,40 +1,3 @@
#******************************************************************************
#
# 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
#
#*****************************************************************************
PACKAGE = propagator PACKAGE = propagator
DESTDIR = DESTDIR =
@ -43,13 +6,49 @@ BINDIR ?= /usr/bin
LIBDIR ?= /usr/lib LIBDIR ?= /usr/lib
BINSDIR ?= $(LIBDIR)/$(PACKAGE)/bin BINSDIR ?= $(LIBDIR)/$(PACKAGE)/bin
INSTALL = /usr/bin/install
TARGETS = init stage1 gencpio TARGETS = init stage1 gencpio
all: version.h $(TARGETS) all: version.h $(TARGETS)
include Makefile.common #---------------------------------------------------------------
L ?= GLIBC
#L = KLIBC
DEFS = ifeq ($(L),KLIBC)
CC = klcc
endif
ifeq ($(F),)
ifeq ($(L),GLIBC)
F = NEWT
else
F = STDIO
endif
endif
CFLAGS += -Os -pipe -Wall
GLIBC_INCLUDES =
KLIBC_INCLUDES =
INCLUDES = $($(L)_INCLUDES)
GCC_LIBDIR=$(shell dirname `gcc -print-libgcc-file-name`)
LIBGCC_A=$(shell gcc -print-libgcc-file-name)
GLIBC_LDFLAGS_STAGE1 = -static
KLIBC_LDFLAGS_STAGE1 =
# $(LIBGCC_A)
LDFLAGS_STAGE1 = $($(L)_LDFLAGS_STAGE1)
GLIBC_LIBC =
KLIBC_LIBC =
STAGE1_LIBC = $($(L)_LIBC)
STRIPCMD = strip -R .note -R .comment
#---------------------------------------------------------------
DEFS = -D_GNU_SOURCE
INIT_DEFS = INIT_DEFS =
STAGE1_DEFS = STAGE1_DEFS =
@ -66,47 +65,34 @@ ifneq ($(WITHOUT_USBNET),)
STAGE1_DEFS += -DDISABLE_USBNET STAGE1_DEFS += -DDISABLE_USBNET
endif endif
COMPILE = $(CC) $(DEFS) $(CFLAGS) COMPILE = $(CC) $(CFLAGS) $(DEFS)
#- stage1 "loader" #- stage1 "loader"
# i386 name is invalid to force this feature off # i386 name is invalid to force this feature off
ifeq (xi386, $(ARCH))
INITSRC = minilibc.c init.c
INIT_DEFS = -DINIT_HEADERS=\"minilibc.h\"
else
INITSRC = init.c INITSRC = init.c
ifeq (ia64, $(ARCH)) INIT_DEFS = $(INCLUDES)
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)) INITOBJS = $(addprefix $(L)-,$(subst .c,.o,$(INITSRC)))
#- frontends #- frontends
NEWT_FRONTEND_SRC = newt-frontend.c NEWT_FRONTEND_SRC = newt-frontend.c
GLIBC_NEWT_FRONTEND_LIBS = $(LIBDIR)/libnewt.a $(LIBDIR)/libslang.a NEWT_FRONTEND_LIBS = $(LIBDIR)/libnewt.a $(LIBDIR)/libslang.a
DIETLIBC_NEWT_FRONTEND_LIBS = $(DIET_LIBDIR)/libnewt.a $(DIET_LIBDIR)/libslang.a
STDIO_FRONTEND_SRC = stdio-frontend.c STDIO_FRONTEND_SRC = stdio-frontend.c
GLIBC_STDIO_FRONTEND_LIBS = STDIO_FRONTEND_LIBS =
DIETLIBC_STDIO_FRONTEND_LIBS =
FRONTEND_OBJS = $(addprefix $(L)-,$(subst .c,.o,$($(F)_FRONTEND_SRC)))
FRONTEND_LINK = $(FRONTEND_OBJS) $($(F)_FRONTEND_LIBS)
FRONTEND_OBJS = $(subst .c,.o,$($(F)_FRONTEND_SRC)) GLIBC_STAGE1_OWN_LIBS =
FRONTEND_LINK = $(FRONTEND_OBJS) $($(L)_$(F)_FRONTEND_LIBS) KLIBC_STAGE1_OWN_LIBS =
GLIBC_STAGE1_OWN_LIBS = $(LIBDIR)/libmar.a $(LIBDIR)/libbz2.a
DIETLIBC_STAGE1_OWN_LIBS = $(DIET_LIBDIR)/libmar.a $(DIET_LIBDIR)/libbz2.a
STAGE1_OWN_LIBS = $($(L)_STAGE1_OWN_LIBS) STAGE1_OWN_LIBS = $($(L)_STAGE1_OWN_LIBS)
ifeq ($(L),KLIBC)
ifeq (DIETLIBC, $(L)) STAGE1_NETWORK_LIBS =
STAGE1_NETWORK_LIBS = $(DIET_LIBDIR)/librpc.a
endif endif
ifeq (GLIBC, $(L)) ifeq ($(L),GLIBC)
STAGE1_NETWORK_LIBS = $(LIBDIR)/libresolv.a STAGE1_NETWORK_LIBS = $(LIBDIR)/libresolv.a
endif endif
@ -116,23 +102,14 @@ STAGE1SRC = stage1.c log.c tools.c modules.c probing.c \
mount.c lomount.c automatic.c frontend-common.c \ mount.c lomount.c automatic.c frontend-common.c \
cdrom.c disk.c \ cdrom.c disk.c \
network.c nfsmount.c dhcp.c url.c dns.c adsl.c network.c nfsmount.c dhcp.c url.c dns.c adsl.c
ALLSRC = $(INITSRC) $(STAGE1SRC) ALLSRC = $(INITSRC) $(STAGE1SRC)
############################################################################### ###############################################################################
STAGE1OBJS = $(subst .c,.o,$(STAGE1SRC)) STAGE1OBJS = $(addprefix $(L)-,$(subst .c,.o,$(STAGE1SRC)))
ifeq (xi386, $(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 = $(GLIBC_LDFLAGS_STAGE1)
INIT_LIBC = $(GLIBC_LIBC)
endif
endif
LDFLAGS_INIT = $($(L)_LDFLAGS_STAGE1)
INIT_LIBC = $($(L)_LIBC)
init: $(INITOBJS) $(INIT_LIBC) init: $(INITOBJS) $(INIT_LIBC)
$(CC) -o $@ $^ $(LDFLAGS_INIT) $(CC) -o $@ $^ $(LDFLAGS_INIT)
@ -142,19 +119,29 @@ stage1: $(STAGE1OBJS) $(STAGE1_OWN_LIBS) $(STAGE1_NETWORK_LIBS) $(FRONTEND_LINK)
$(CC) -o $@ $^ $(LDFLAGS_STAGE1) $(CC) -o $@ $^ $(LDFLAGS_STAGE1)
$(STRIPCMD) $@ $(STRIPCMD) $@
$(INITOBJS): %.o: %.c $(INITOBJS): $(L)-%.o: %.c
$(COMPILE) $(INIT_DEFS) -c $< $(COMPILE) $(INIT_DEFS) -c $< -o $@
$(STAGE1OBJS): %.o: %.c $(STAGE1OBJS): $(L)-%.o: %.c
$(COMPILE) $(INCLUDES) $(STAGE1_DEFS) -c $< -o $@ $(COMPILE) $(INCLUDES) $(STAGE1_DEFS) -c $< -o $@
.c.o: $(FRONTEND_OBJS): $(L)-%.o: %.c
$(COMPILE) $(INCLUDES) -c $< $(COMPILE) $(INCLUDES) -c $< -o $@
version.h: /etc/altlinux-release version.h: /etc/altlinux-release
@sed 's|^ALT Linux \([^ ]\+\)\([^(]\+\)(\([^)]\+\))|\ @sed 's|^ALT Linux \([^ ]\+\)\([^(]\+\)(\([^)]\+\))|\
echo \\#define VERSION \\"\2\\";echo \\#define DISTRIB_NAME \\"ALT Linux\2\1 \\(\3\\)\\"|' < $^ |sh > $@ echo \\#define VERSION \\"\2\\";echo \\#define DISTRIB_NAME \\"ALT Linux\2\1 \\(\3\\)\\"|' < $^ |sh > $@
gencpio: gen_init_cpio.c
$(CC) $(CFLAGS) $(DEFS) -o $@ $^
initfs: mkinitfs $(TARGETS)
sh $< $@
install: initfs
$(INSTALL) -D -m0755 gencpio $(DESTDIR)$(BINDIR)/gencpio
$(INSTALL) -D -m0644 initfs $(DESTDIR)$(LIBDIR)/$(PACKAGE)/initfs
clean: clean:
rm -f *.o .depend $(TARGETS) version.h rm -f *.o .depend $(TARGETS) version.h
@ -164,11 +151,3 @@ clean:
ifeq (.depend,$(wildcard .depend)) ifeq (.depend,$(wildcard .depend))
include .depend include .depend
endif endif
gencpio: gen_init_cpio.c
$(CC) $(CFLAGS) -o $@ $^
install: $(TARGETS)
mkdir -p $(DESTDIR)$(BINDIR) $(DESTDIR)$(BINSDIR)
install -m0755 gencpio $(DESTDIR)$(BINDIR)
install -m0755 init stage1 $(DESTDIR)$(BINSDIR)

View File

@ -1,59 +0,0 @@
# -*- 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.
#
#*****************************************************************************
#include /usr/lib/dietlibc/Makefile.rules
#DIET_LIBDIR = /usr/lib/dietlibc/lib-$(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
#- flags used by all stuff
ifeq (ppc, $(ARCH))
CFLAGS += -Os -pipe -Wall -fomit-frame-pointer
else
CFLAGS += -pipe -Wall -O2 -D_GNU_SOURCE
endif
GLIBC_INCLUDES =
INCLUDES = -I. $($(L)_INCLUDES)
GCC_LIBDIR=$(shell dirname `gcc -print-libgcc-file-name`)
LIBGCC_A=$(shell gcc -print-libgcc-file-name)
GLIBC_LDFLAGS_STAGE1 = -static
DIETLIBC_LDFLAGS_STAGE1 = -nostdlib
# $(LIBGCC_A)
LDFLAGS_STAGE1 = $($(L)_LDFLAGS_STAGE1)
GLIBC_LIBC =
DIETLIBC_LIBC = $(DIET_LIBDIR)/libc.a $(DIET_LIBDIR)/libcompat.a
STAGE1_LIBC = $($(L)_LIBC)
STRIPCMD = strip -R .note -R .comment

6
adsl.c
View File

@ -145,9 +145,9 @@ enum return_type perform_adsl(struct interface_info * intf)
intf->boot_proto = BOOTPROTO_ADSL_PPPOE; intf->boot_proto = BOOTPROTO_ADSL_PPPOE;
wait_message("Waiting for ADSL connection to show up..."); wait_message("Waiting for ADSL connection to show up...");
my_insmod("ppp_generic", ANY_DRIVER_TYPE, NULL); my_insmod("ppp_generic", NULL);
my_insmod("ppp_async", ANY_DRIVER_TYPE, NULL); my_insmod("ppp_async", NULL);
my_insmod("ppp", ANY_DRIVER_TYPE, NULL); my_insmod("ppp", NULL);
results = adsl_connect(intf->device, answers[0], answers[1]); results = adsl_connect(intf->device, answers[0], answers[1]);
remove_wait_message(); remove_wait_message();

10
cdrom.c
View File

@ -113,8 +113,8 @@ enum return_type cdrom_prepare(void)
char * choice; char * choice;
int i, count = 0; int i, count = 0;
enum return_type results; enum return_type results;
my_insmod("ide-cd", ANY_DRIVER_TYPE, NULL); my_insmod("ide-cd", NULL);
my_insmod("sr_mod", ANY_DRIVER_TYPE, NULL); my_insmod("sr_mod", NULL);
update_splash(); update_splash();
get_medias(CDROM, &medias, &medias_models); get_medias(CDROM, &medias, &medias_models);
@ -127,7 +127,7 @@ enum return_type cdrom_prepare(void)
if (count == 0) { if (count == 0) {
stg1_error_message("No CDROM device found."); stg1_error_message("No CDROM device found.");
i = ask_insmod(MEDIA_ADAPTERS); i = ask_insmod();
if (i == RETURN_BACK) if (i == RETURN_BACK)
return RETURN_BACK; return RETURN_BACK;
return cdrom_prepare(); return cdrom_prepare();
@ -137,7 +137,7 @@ enum return_type cdrom_prepare(void)
results = try_with_device(*medias, *medias_models); results = try_with_device(*medias, *medias_models);
if (results == RETURN_OK) if (results == RETURN_OK)
return RETURN_OK; return RETURN_OK;
i = ask_insmod(MEDIA_ADAPTERS); i = ask_insmod();
if (i == RETURN_BACK) if (i == RETURN_BACK)
return RETURN_BACK; return RETURN_BACK;
return cdrom_prepare(); return cdrom_prepare();
@ -187,7 +187,7 @@ enum return_type cdrom_prepare(void)
if (results == RETURN_BACK) if (results == RETURN_BACK)
return cdrom_prepare(); return cdrom_prepare();
i = ask_insmod(MEDIA_ADAPTERS); i = ask_insmod();
if (i == RETURN_BACK) if (i == RETURN_BACK)
return RETURN_BACK; return RETURN_BACK;
return cdrom_prepare(); return cdrom_prepare();

10
disk.c
View File

@ -282,8 +282,8 @@ enum return_type disk_prepare(void)
int i, count = 0; int i, count = 0;
enum return_type results; enum return_type results;
my_insmod("ide-disk", ANY_DRIVER_TYPE, NULL); my_insmod("ide-disk", NULL);
my_insmod("sd_mod", ANY_DRIVER_TYPE, NULL); my_insmod("sd_mod", NULL);
get_medias(DISK, &medias, &medias_models); get_medias(DISK, &medias, &medias_models);
ptr = medias; ptr = medias;
@ -294,7 +294,7 @@ enum return_type disk_prepare(void)
if (count == 0) { if (count == 0) {
stg1_error_message("No DISK drive found."); stg1_error_message("No DISK drive found.");
i = ask_insmod(MEDIA_ADAPTERS); i = ask_insmod();
if (i == RETURN_BACK) if (i == RETURN_BACK)
return RETURN_BACK; return RETURN_BACK;
return disk_prepare(); return disk_prepare();
@ -304,7 +304,7 @@ enum return_type disk_prepare(void)
results = try_with_device(*medias); results = try_with_device(*medias);
if (results == RETURN_OK) if (results == RETURN_OK)
return RETURN_OK; return RETURN_OK;
i = ask_insmod(MEDIA_ADAPTERS); i = ask_insmod();
if (i == RETURN_BACK) if (i == RETURN_BACK)
return RETURN_BACK; return RETURN_BACK;
return disk_prepare(); return disk_prepare();
@ -319,7 +319,7 @@ enum return_type disk_prepare(void)
results = try_with_device(choice); results = try_with_device(choice);
if (results == RETURN_OK) if (results == RETURN_OK)
return RETURN_OK; return RETURN_OK;
i = ask_insmod(MEDIA_ADAPTERS); i = ask_insmod();
if (i == RETURN_BACK) if (i == RETURN_BACK)
return RETURN_BACK; return RETURN_BACK;
return disk_prepare(); return disk_prepare();

View File

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

View File

@ -1,53 +0,0 @@
/*
* 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 <dirent.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <fcntl.h>
#ifdef __LIBC_DIETLIBC__
#include <sys/i386-ioctl.h>
#endif
#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);
#ifdef __LIBC_DIETLIBC__
char ** environ = NULL;
#endif

271
init.c
View File

@ -19,11 +19,18 @@
* *
*/ */
#ifndef INIT_HEADERS #include <errno.h>
#include "init-libc-headers.h" #include <string.h>
#else #include <stdlib.h>
#include INIT_HEADERS #include <stdio.h>
#endif #include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/klog.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <sys/wait.h>
#include "config-stage1.h" #include "config-stage1.h"
@ -31,9 +38,13 @@
#define TIOCSCTTY 0x540 #define TIOCSCTTY 0x540
#endif #endif
#define MKDEV(ma,mi) ((ma)<<8 | (mi))
#define RAMFS_MAGIC 0x858458f6
#define TMPFS_MAGIC 0x01021994
char * env[] = { char * env[] = {
"PATH=/usr/bin:/bin:/sbin:/usr/sbin:/usr/X11R6/bin", "PATH=/usr/bin:/bin:/sbin:/usr/sbin",
"LD_LIBRARY_PATH=/lib:/usr/lib:/usr/X11R6/lib", "LD_LIBRARY_PATH=/lib:/usr/lib",
"HOME=/", "HOME=/",
"TERM=linux", "TERM=linux",
"TERMINFO=/etc/terminfo", "TERMINFO=/etc/terminfo",
@ -42,6 +53,11 @@ char * env[] = {
char ** myenv = NULL; char ** myenv = NULL;
char *stage[] = {"/sbin/stage1", NULL};
char *udevd[] = {"/sbin/udevd", NULL};
char *udevtrigger[] = {"/sbin/udevtrigger", NULL};
char *udevsettle[] = {"/sbin/udevsettle", NULL};
/* /*
* this needs to handle the following cases: * this needs to handle the following cases:
* *
@ -51,21 +67,14 @@ char ** myenv = NULL;
* 4) run from a floppy that's been loaded into a ramdisk * 4) run from a floppy that's been loaded into a ramdisk
*/ */
int klog_pid; void fatal(const char *msg)
void fatal_error(const char *msg)
{ {
printf("FATAL ERROR IN INIT: %s : %s\n\nI can't recover from this, please reboot manually and send bugreport.\n", msg,strerror(errno)); printf("FATAL ERROR IN INIT: %s\nI can't recover from this,"
"please reboot manually and send bugreport.\n", msg);
while (1); while (1);
} }
void print_error(char *msg) void warn(char *msg)
{
printf("E: %s\n", msg);
}
void print_warning(char *msg)
{ {
printf("W: %s\n", msg); printf("W: %s\n", msg);
} }
@ -74,52 +83,50 @@ void print_warning(char *msg)
* (1) watch /proc/kmsg and copy the stuff to /dev/tty4 * (1) watch /proc/kmsg and copy the stuff to /dev/tty4
* (2) listens to /dev/log and copy also this stuff (log from programs) * (2) listens to /dev/log and copy also this stuff (log from programs)
*/ */
void doklog() pid_t doklog()
{ {
int in, out, i, ii; int in, out, i, ii;
int log; pid_t pid;
char buf[1024]; char buf[1024];
/* open kernel message logger */ /* open kernel message logger */
in = open("/proc/kmsg", O_RDONLY,0); if ((in = open("/proc/kmsg", O_RDONLY, 0)) < 0)
if (in < 0) { fatal("failed to open /proc/kmsg");
print_error("could not open /proc/kmsg");
return;
}
if ((log = open("/tmp/syslog", O_WRONLY | O_CREAT, 0644)) < 0) { if (mknod("/dev/tty4", S_IFCHR, MKDEV(4, 4)) < 0 ||
perror("/tmp/syslog"); (out = open("/dev/tty4", O_WRONLY, 0)) < 0)
print_error("error opening /tmp/syslog"); fatal("failed to open /dev/tty4");
sleep(5);
return;
}
if ((klog_pid = fork())) { if ((pid = fork())) {
if (pid < 0) fatal("doklog");
close(in); close(in);
close(log); close(out);
return; return pid;
} else { }
/* child */
close(0); close(0);
close(1); close(1);
close(2); close(2);
}
out = open("/dev/tty4", O_WRONLY, 0);
if (out < 0) {
perror("can't open /dev/tty4");
print_warning("couldn't open tty for syslog -- still using /tmp/syslog\n");
}
/* disable on-console syslog output */ /* disable on-console syslog output */
syslog(8, NULL, 1); klogctl(8, NULL, 1);
while (1) { while (1)
i = read(in, buf, sizeof(buf)); if ((i = read(in, buf, sizeof(buf))) > 0)
if (i > 0) {
if (out >= 0)
ii = write(out, buf, i); ii = write(out, buf, i);
ii = write(log, buf, i); }
}
pid_t spawn(char *av[])
{
pid_t pid;
if ((pid = fork())) {
if (pid < 0) fatal(av[0]);
return pid;
} else {
execve(av[0], av, env);
perror(av[0]);
exit(1);
} }
} }
@ -131,7 +138,7 @@ void grab_env(int fd)
int i; int i;
if ((i = read(fd, buf, sizeof(buf))) < 0) { if ((i = read(fd, buf, sizeof(buf))) < 0) {
print_error("failed to read env from pipe"); warn("failed to read env from pipe");
myenv = env; myenv = env;
return; return;
} }
@ -140,7 +147,7 @@ void grab_env(int fd)
buf[i] = '\0'; buf[i] = '\0';
if ((ep = myenv = malloc(sizeof(char *) * 32)) == NULL) { if ((ep = myenv = malloc(sizeof(char *) * 32)) == NULL) {
print_error("can't malloc env"); warn("can't malloc env");
myenv = env; myenv = env;
return; return;
} }
@ -252,7 +259,7 @@ static int nuke(const char *what)
if ( err ) { if ( err ) {
errno = err; errno = err;
fatal_error(what); fatal(what);
} }
return 0; return 0;
} }
@ -279,7 +286,7 @@ void unmount_filesystems(void)
fd = open("/proc/mounts", O_RDONLY, 0); fd = open("/proc/mounts", O_RDONLY, 0);
if (fd < 1) { if (fd < 1) {
print_error("failed to open /proc/mounts"); warn("failed to open /proc/mounts");
sleep(2); sleep(2);
return; return;
} }
@ -332,66 +339,89 @@ void unmount_filesystems(void)
} }
if (nb) { if (nb) {
printf("failed to umount some filesystems\n"); fatal("failed to umount some filesystems\n");
while (1);
} }
} }
#define MAJOR(dev) ((dev)>>8)
#define MINOR(dev) ((dev) & 0xff)
#define MKDEV(ma,mi) ((ma)<<8 | (mi))
#define DEV_PERM 00400|00200|00040|00020
#define CHR_DEV 0020000|DEV_PERM
#define BLK_DEV 0060000|DEV_PERM
#define RAMFS_MAGIC 0x858458f6
#define TMPFS_MAGIC 0x01021994
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct stat rst, cst, ist; struct stat rst, cst, ist;
struct statfs sfs; struct statfs sfs;
pid_t installpid, childpid; pid_t pid, klogpid, udevpid;
int wait_status; int wait_status;
int fd; int fd = -1;
int fds[2]; int fds[2];
int end_stage1 = 0;
if (mount("/proc", "/proc", "proc", 0, NULL)) if (mount("/proc", "/proc", "proc", 0, NULL))
fatal_error("Unable to mount proc filesystem"); fatal("failed to mount proc filesystem");
if (mount("/sysfs", "/sys", "sysfs", 0, NULL)) if (mount("sysfs", "/sys", "sysfs", 0, NULL))
fatal_error("Unable to mount sysfs filesystem"); fatal("failed to mount sysfs filesystem");
if (mount("udev", "/dev", "tmpfs", 0, "size=10M,mode=0755"))
fatal("failed to mount tmpfs filesystem");
/* ignore Control-C and keyboard stop signals */ /* ignore Control-C and keyboard stop signals */
signal(SIGINT, SIG_IGN); signal(SIGINT, SIG_IGN);
signal(SIGTSTP, SIG_IGN); signal(SIGTSTP, SIG_IGN);
fd = open("/dev/console", O_RDWR, 0); if (mknod("/dev/console", S_IFCHR, MKDEV(5, 1)) < 0 ||
if (fd < 0) (fd = open("/dev/console", O_RDWR, 0)) < 0) {
fatal_error("failed to open /dev/console"); fatal("failed to open /dev/console");
}
dup2(fd, 0); dup2(fd, 0);
dup2(fd, 1); dup2(fd, 1);
dup2(fd, 2); dup2(fd, 2);
close(fd); close(fd);
if (mknod("/dev/null", S_IFCHR, MKDEV(1, 3)) < 0)
fatal("failed to create /dev/null");
/* I set me up as session leader (probably not necessary?) */ /* I set me up as session leader (probably not necessary?) */
setsid(); setsid();
if (ioctl(0, TIOCSCTTY, NULL)) { if (ioctl(0, TIOCSCTTY, NULL)) {
perror("TIOCSCTTY"); perror("TIOCSCTTY");
print_error("could not set new controlling tty"); warn("could not set new controlling tty");
} }
char my_hostname[] = "localhost.localdomain"; if (sethostname("localhost.localdomain", sizeof("localhost.localdomain")) < 0)
if (sethostname(my_hostname, sizeof(my_hostname)) < 0) warn("could not set hostname");
print_error("could not set hostname");
/* the default domainname (as of 2.0.35) is "(none)", which confuses glibc */ /* the default domainname (as of 2.0.35) is "(none)", which confuses glibc */
if (setdomainname("", 0) < 0) if (setdomainname("", 0) < 0)
print_error("could not set domainname"); warn("could not set domainname");
doklog(); if (mkdir("/dev/.initramfs", 0755) < 0 ||
mkdir("/dev/pts", 0755) < 0 ||
mkdir("/dev/shm", 0755) < 0)
fatal("mkdir\n");
if ((fd = open("/proc/sys/kernel/hotplug", O_WRONLY, 0)) < 0 ||
write(fd, "\n", sizeof("\n")) < sizeof("\n"))
fatal("/proc/sys/kernel/hotplug\n");
close(fd);
klogpid = doklog();
if (mkdir("/dev/.udev", 0755) < 0 ||
mkdir("/dev/.udev/db", 0755) < 0)
fatal("/dev/.udev/db");
printf("Spawning udevd...");
udevpid = spawn(udevd);
if (mkdir("/dev/.udev/queue", 0755) < 0 && errno != EEXIST)
fatal("cannot create /dev/.udev/queue");
if (waitpid(spawn(udevtrigger), &wait_status, 0) < 0 ||
!(WIFEXITED(wait_status)))
warn("udevtrigger");
if (waitpid(spawn(udevsettle), &wait_status, 0) < 0 ||
!(WIFEXITED(wait_status)))
warn("udevsettle");
printf("done\n");
/* Go into normal init mode - keep going, and then do a orderly shutdown /* Go into normal init mode - keep going, and then do a orderly shutdown
when: when:
@ -404,33 +434,19 @@ int main(int argc, char **argv)
/* create a pipe for env passing */ /* create a pipe for env passing */
if (pipe(fds) < 0) if (pipe(fds) < 0)
fatal_error("failed to create env pipe"); fatal("failed to create env pipe");
fcntl(fds[0], F_SETFD, 1); fcntl(fds[0], F_SETFD, 1);
fcntl(fds[1], F_SETFD, 0); fcntl(fds[1], F_SETFD, 0);
if (!(installpid = fork())) { pid = spawn(stage);
/* 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;
}
close(fds[1]); close(fds[1]);
while (pid != wait(&wait_status));
while (!end_stage1) {
childpid = wait4(-1, &wait_status, 0, NULL);
if (childpid == installpid)
end_stage1 = 1;
}
if (!(WIFEXITED(wait_status))) { if (!(WIFEXITED(wait_status))) {
/* something went wrong */ /* something went wrong */
printf("wait_status: %i, install exited abnormally :-( ", wait_status); printf("wait_status: %i, install exited abnormally ", wait_status);
if (WIFSIGNALED(wait_status)) if (WIFSIGNALED(wait_status))
printf("-- received signal %d", WTERMSIG(wait_status)); printf("-- received signal %d", WTERMSIG(wait_status));
printf("\n"); printf("\n");
@ -455,15 +471,23 @@ int main(int argc, char **argv)
grab_env(fds[0]); grab_env(fds[0]);
kill(klog_pid, 9); if (waitpid(spawn(udevsettle), &wait_status, 0) < 0 ||
waitpid(klog_pid, &wait_status, 0); !(WIFEXITED(wait_status)))
warn("udevsettle");
kill(udevpid, 9);
waitpid(udevpid, &wait_status, 0);
nuke_dir("/dev/.udev/queue");
kill(klogpid, 9);
waitpid(klogpid, &wait_status, 0);
printf("Spawning init ..."); printf("Spawning init ...");
/* rest was seamlessy stolen from klibc */ /* rest was seamlessy stolen from klibc */
/* First, change to the new root directory */ /* First, change to the new root directory */
if (chdir(STAGE2_LOCATION)) if (chdir(STAGE2_LOCATION))
fatal_error("chdir to new root"); fatal("chdir to new root");
/* This is a potentially highly destructive program. Take some /* This is a potentially highly destructive program. Take some
extra precautions. */ extra precautions. */
@ -471,71 +495,66 @@ int main(int argc, char **argv)
/* Make sure the current directory is not on the same filesystem /* Make sure the current directory is not on the same filesystem
as the root directory */ as the root directory */
if ( stat("/", &rst) || stat(".", &cst) ) if ( stat("/", &rst) || stat(".", &cst) )
fatal_error("stat"); fatal("stat");
if ( rst.st_dev == cst.st_dev ) if ( rst.st_dev == cst.st_dev )
fatal_error("current directory on the same filesystem as the root"); fatal("current directory on the same filesystem as the root");
/* The initramfs should have /init */ /* The initramfs should have /init */
if ( stat("/init", &ist) || !S_ISREG(ist.st_mode) ) if ( stat("/init", &ist) || !S_ISREG(ist.st_mode) )
fatal_error("can't find /init on initramfs"); fatal("can't find /init on initramfs");
/* Make sure we're on a ramfs */ /* Make sure we're on a ramfs */
if ( statfs("/", &sfs) ) if ( statfs("/", &sfs) )
fatal_error("statfs /"); fatal("statfs /");
if ( sfs.f_type != RAMFS_MAGIC && sfs.f_type != TMPFS_MAGIC ) if ( sfs.f_type != RAMFS_MAGIC && sfs.f_type != TMPFS_MAGIC )
fatal_error("rootfs not a ramfs or tmpfs"); fatal("rootfs not a ramfs or tmpfs");
/* Okay, I think we should be safe... */ /* Okay, I think we should be safe... */
/* overmount image under new root if needed */ /* overmount image under new root if needed */
if ( statfs(IMAGE_LOCATION, &sfs) ) if ( statfs(IMAGE_LOCATION, &sfs) )
fatal_error("statfs "IMAGE_LOCATION); fatal("statfs "IMAGE_LOCATION);
/* if something is mounted under IMAGE_LOCATION ? */ /* if something is mounted under IMAGE_LOCATION ? */
if ( sfs.f_type != RAMFS_MAGIC && sfs.f_type != TMPFS_MAGIC ) { if ( sfs.f_type != RAMFS_MAGIC && sfs.f_type != TMPFS_MAGIC ) {
if ( mount(IMAGE_LOCATION, "." IMAGE_LOCATION, NULL, MS_MOVE, NULL) ) if ( mount(IMAGE_LOCATION, "." IMAGE_LOCATION, NULL, MS_MOVE, NULL) )
fatal_error("overmounting image location"); fatal("overmounting image location");
/* test for nested mount: disk or nfs with iso image */ /* test for nested mount: disk or nfs with iso image */
if ( statfs(IMAGE_LOCATION, &sfs) ) if ( statfs(IMAGE_LOCATION, &sfs) )
fatal_error("nested statfs "IMAGE_LOCATION); fatal("nested statfs "IMAGE_LOCATION);
if ( sfs.f_type != RAMFS_MAGIC && sfs.f_type != TMPFS_MAGIC ) if ( sfs.f_type != RAMFS_MAGIC && sfs.f_type != TMPFS_MAGIC )
if ( mount(IMAGE_LOCATION, "." IMAGE_LOCATION "/isolinux", NULL, MS_MOVE, NULL) ) if ( mount(IMAGE_LOCATION, "." IMAGE_LOCATION "/isolinux", NULL, MS_MOVE, NULL) )
fatal_error("overmounting nested image location"); fatal("overmounting nested image location");
} }
umount("/sys"); umount("/sys");
umount("/proc/bus/usb"); umount("/proc/bus/usb");
umount("/proc"); umount("/proc");
if (mount("/dev", "./dev", NULL, MS_MOVE, NULL))
fatal("overmounting /dev");
/* Delete rootfs contents */ /* Delete rootfs contents */
if ( nuke_dir("/") ) if (nuke_dir("/"))
fatal_error("nuking initramfs contents"); fatal("nuking initramfs contents");
/* Overmount the root */ /* Overmount the root */
if ( mount(".", "/", NULL, MS_MOVE, NULL) ) if (mount(".", "/", NULL, MS_MOVE, NULL))
fatal_error("overmounting root"); fatal("overmounting root");
/* chroot, chdir */ /* chroot, chdir */
if (chroot(".") || chdir("/")) if (chroot(".") || chdir("/"))
fatal_error("chroot"); fatal("chroot");
/* Open /dev/console */
if ((fd = open("/dev/console", O_RDWR)) != -1) {
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
close(fd);
}
/* Check for given init */ /* Check for given init */
if (stat(STAGE2_BINNAME, &ist) || !S_ISREG(ist.st_mode)) if (stat(STAGE2_BINNAME, &ist) || !S_ISREG(ist.st_mode))
fatal_error("can't find init on root fs"); fatal("can't find init on root fs");
/* Spawn init */ /* Spawn init */
printf(" done.\n"); printf(" done.\n");
argv[0] = STAGE2_BINNAME; argv[0] = STAGE2_BINNAME;
execve(argv[0], argv, myenv); execve(argv[0], argv, myenv);
fatal_error("stage2"); /* Failed to spawn init */ fatal("stage2"); /* Failed to spawn init */
return 0; return 0;
} }

View File

@ -63,14 +63,15 @@ int
set_loop (const char *device, const char *file) set_loop (const char *device, const char *file)
{ {
struct loop_info loopinfo; struct loop_info loopinfo;
int fd, ffd, mode; int i, fd, ffd, mode;
mode = O_RDONLY; mode = O_RDONLY;
if ((ffd = open (file, mode)) < 0) if ((ffd = open (file, mode)) < 0)
return 1; return 1;
if ((fd = open (device, mode)) < 0) { for (i=3; i && (fd = open(device, mode)) < 0; --i, sleep(1));
if (fd < 0) {
close(ffd); close(ffd);
return 1; return 1;
} }
@ -139,7 +140,7 @@ lomount(char *loopfile, char *where)
flag = MS_MGC_VAL; flag = MS_MGC_VAL;
flag |= MS_RDONLY; flag |= MS_RDONLY;
my_insmod("loop", ANY_DRIVER_TYPE, NULL); my_insmod("loop", NULL);
if (set_loop(loopdev, loopfile)) { if (set_loop(loopdev, loopfile)) {
log_message("set_loop failed on %s (%s)", loopdev, strerror(errno)); log_message("set_loop failed on %s (%s)", loopdev, strerror(errno));

View File

@ -1,251 +0,0 @@
/*
* 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;
}
}
}

View File

@ -1,144 +0,0 @@
/*
* 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)));

62
mkinitfs Executable file
View File

@ -0,0 +1,62 @@
#!/bin/sh -e
out=$1
shift
[ -n "$out" ] || {
echo "Usage: mkinitfs outfile" >&2
exit 1
}
exit_handler()
{
local rc=$?
trap - EXIT
[ $rc -eq 0 ] || rm -f -- $out
exit $rc
}
trap exit_handler HUP PIPE INT TERM QUIT EXIT
(
cat <<EOF
dir /dev 0755 0 0
dir /image 0755 0 0
dir /proc 0755 0 0
dir /sys 0755 0 0
dir /root 0755 0 0
dir /tmp 0755 0 0
dir /var 0755 0 0
dir /var/lock 0755 0 0
dir /etc 0755 0 0
dir /etc/modprobe.d 0755 0 0
dir /etc/terminfo 0755 0 0
dir /etc/terminfo/l 0755 0 0
file /etc/terminfo/l/linux /lib/terminfo/l/linux 0644 0 0
dir /etc/udev 0755 0 0
dir /etc/udev/rules.d 0755 0 0
dir /lib 0755 0 0
dir /lib/udev 0755 0 0
dir /bin 0755 0 0
file /bin/sh /lib/mkinitrd/busybox 0755 0 0
dir /sbin 0755 0 0
file /sbin/modprobe /lib/mkinitrd/module-init-tools/sbin/modprobe 0755 0 0
file /sbin/stage1 stage1 0755 0 0
file /init init 0755 0 0
EOF
find /lib/mkinitrd/klibc/lib -xtype f|\
sed -e 's,/lib/mkinitrd/klibc,,' -e 's,^.\+$,file\t&\t/lib/mkinitrd/klibc&\t0755\t0 0,g'
find /lib/mkinitrd/udev -type f|\
sed -e 's,/lib/mkinitrd/udev,,' -e 's,^.\+$,file\t&\t/lib/mkinitrd/udev&\t0755\t0 0,g'
find /etc/modprobe.d/ /etc/udev/rules.d -type f|\
sed -e 's,^.\+$,file\t&\t&\t0644\t0 0,g'
) | `pwd`/gencpio - |gzip -c > $out

298
modules.c
View File

@ -21,6 +21,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/wait.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
@ -28,25 +29,12 @@
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#ifdef CONFIG_USE_ZLIB
#include <zlib.h>
#endif
#include "stage1.h" #include "stage1.h"
#include "log.h" #include "log.h"
#include "frontend.h" #include "frontend.h"
#include "mount.h" #include "mount.h"
#include "modules_descr.h"
#include "modules.h" #include "modules.h"
extern int mar_extract_inplace(char *, const char *, void **, int *);
extern char ** mar_list_contents(char *);
static struct module_deps_elem * modules_deps = NULL;
static char * archive_name = "/modules/modules.mar";
int disable_modules = 0;
static const char *moderror(int err) static const char *moderror(int err)
{ {
switch (err) { switch (err) {
@ -108,295 +96,45 @@ int insmod_call(char *pathname, char *params)
return 0; return 0;
} }
static enum insmod_return insmod_archived_file(const char * mod_name, char * options) static enum insmod_return modprobe(const char * mod_name, char * options)
{ {
void *file; int pid, status;
char module_name[50]; if (!(pid = fork())) {
int len, i, rc; char * argv[4];
argv[0] = "/sbin/modprobe";
strncpy(module_name, mod_name, sizeof(module_name)); argv[1] = mod_name;
strcat(module_name, ".ko"); argv[2] = options;
i = mar_extract_inplace(archive_name, module_name, &file, &len); argv[3] = NULL;
if (i == 1) { execve(argv[0], argv, NULL);
log_message("file-not-found-in-archive %s", module_name); log_message("modprobe %s failed", mod_name);
return INSMOD_FAILED_FILE_NOT_FOUND;
} }
if (i != 0) waitpid(pid, &status, 0);
return INSMOD_FAILED; return WIFEXITED(status) ? INSMOD_OK : INSMOD_FAILED;
rc = init_module(file, len, options == NULL ? "" : options);
free(file);
if (rc != 0 && errno != EEXIST) {
log_message("init_module: '%s': %s", module_name, moderror(errno));
return INSMOD_FAILED;
}
return INSMOD_OK;
} }
static int load_modules_dependencies(void) enum insmod_return my_insmod(const char * mod_name, char * options)
{ {
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 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; int i;
#ifndef DISABLE_NETWORK
char ** net_devices = NULL;
#endif
log_message("have to insmod %s", mod_name); log_message("have to insmod %s", mod_name);
if (disable_modules) {
log_message("\tdisabled");
return INSMOD_OK;
}
#ifndef DISABLE_NETWORK
if (type == NETWORK_DEVICES || type == BRIDGE_OTHER)
net_devices = get_net_devices();
#endif
if (IS_TESTING) if (IS_TESTING)
return INSMOD_OK; return INSMOD_OK;
i = insmod_with_deps(mod_name, options); i = modprobe(mod_name, options);
if (i == 0) { if (i == 0) {
log_message("\tsucceeded %s", mod_name); log_message("\tsucceeded %s", mod_name);
#ifndef DISABLE_MEDIAS
if (type == MEDIA_ADAPTERS) {
log_message("MEDIA: %s", alias);
}
#endif
#ifndef DISABLE_NETWORK
if (type == NETWORK_DEVICES || type == BRIDGE_OTHER) {
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++;
}
log_message("NET: %s", alias);
net_discovered_interface(*new_net_devices);
already_present:
new_net_devices++;
}
}
#endif
} else } else
log_message("warning, insmod failed (%s %s) (%d)", mod_name, options, i); log_message("warning, insmod failed (%s %s) (%d)", mod_name, options, i);
return i; return i;
} }
static enum return_type insmod_with_options(char * mod, enum driver_type type) enum return_type ask_insmod()
{ {
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; return RETURN_ERROR;
}
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 == MEDIA_ADAPTERS)
mytype = "IDE or 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) void update_modules(void)
{ {
FILE * f; FILE * f;
@ -406,7 +144,7 @@ void update_modules(void)
stg1_info_message("Please insert the Update Modules floppy.");; stg1_info_message("Please insert the Update Modules floppy.");;
my_insmod("floppy", ANY_DRIVER_TYPE, NULL); my_insmod("floppy", NULL);
if (my_mount("/dev/fd0", floppy_mount_location, "ext2", 0) == -1) { 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" enum return_type results = ask_yes_no("I can't find a Linux ext2 floppy in first floppy drive.\n"
@ -453,7 +191,7 @@ void update_modules(void)
entry++; entry++;
} }
if (!entry || !*entry) { if (!entry || !*entry) {
enum insmod_return ret = my_insmod(module, ANY_DRIVER_TYPE, options); enum insmod_return ret = my_insmod(module, options);
if (ret != INSMOD_OK) { if (ret != INSMOD_OK) {
log_message("\t%s (marfile): failed", module); log_message("\t%s (marfile): failed", module);
stg1_error_message("Insmod %s (marfile) failed.", module); stg1_error_message("Insmod %s (marfile) failed.", module);

View File

@ -22,16 +22,8 @@ extern long init_module(void *, unsigned long, const char *);
enum insmod_return { INSMOD_OK, INSMOD_FAILED, INSMOD_FAILED_FILE_NOT_FOUND }; enum insmod_return { INSMOD_OK, INSMOD_FAILED, INSMOD_FAILED_FILE_NOT_FOUND };
void init_modules_insmoding(void); enum return_type ask_insmod();
enum insmod_return my_insmod(const char * mod_name, enum driver_type type, char * options); enum insmod_return my_insmod(const char * mod_name, char * options);
enum return_type ask_insmod(enum driver_type);
void update_modules(void); void update_modules(void);
struct module_deps_elem {
char * name;
char ** deps;
};
extern int disable_modules;
#endif #endif

14
mount.c
View File

@ -157,29 +157,29 @@ int my_mount(char *dev, char *location, char *fs, int force_rw)
#ifndef DISABLE_MEDIAS #ifndef DISABLE_MEDIAS
if (!strcmp(fs, "squashfs")) if (!strcmp(fs, "squashfs"))
my_insmod("squashfs", ANY_DRIVER_TYPE, NULL); my_insmod("squashfs", NULL);
if (!strcmp(fs, "ext2")) if (!strcmp(fs, "ext2"))
my_insmod("ext2", ANY_DRIVER_TYPE, NULL); my_insmod("ext2", NULL);
if (!strcmp(fs, "vfat")) { if (!strcmp(fs, "vfat")) {
my_insmod("vfat", ANY_DRIVER_TYPE, NULL); my_insmod("vfat", NULL);
opts = "check=relaxed"; opts = "check=relaxed";
} }
if (!strcmp(fs, "ntfs")) if (!strcmp(fs, "ntfs"))
my_insmod("ntfs", ANY_DRIVER_TYPE, NULL); my_insmod("ntfs", NULL);
if (!strcmp(fs, "reiserfs")) if (!strcmp(fs, "reiserfs"))
my_insmod("reiserfs", ANY_DRIVER_TYPE, NULL); my_insmod("reiserfs", NULL);
if (!strcmp(fs, "iso9660")) if (!strcmp(fs, "iso9660"))
my_insmod("isofs", ANY_DRIVER_TYPE, NULL); my_insmod("isofs", NULL);
#endif #endif
#ifndef DISABLE_NETWORK #ifndef DISABLE_NETWORK
if (!strcmp(fs, "nfs")) { if (!strcmp(fs, "nfs")) {
my_insmod("nfs", ANY_DRIVER_TYPE, NULL); my_insmod("nfs", NULL);
log_message("preparing nfsmount for %s", dev); log_message("preparing nfsmount for %s", dev);
rc = nfsmount_prepare(dev, &opts); rc = nfsmount_prepare(dev, &opts);
if (rc != 0) if (rc != 0)

View File

@ -515,7 +515,7 @@ static enum return_type bringup_networking(struct interface_info * intf)
static struct interface_info loopback; static struct interface_info loopback;
enum return_type results = RETURN_ERROR; enum return_type results = RETURN_ERROR;
my_insmod("af_packet", ANY_DRIVER_TYPE, NULL); my_insmod("af_packet", NULL);
while (results != RETURN_OK) { while (results != RETURN_OK) {
results = setup_network_interface(intf); results = setup_network_interface(intf);
@ -563,7 +563,7 @@ static char * interface_select(void)
if (count == 0) { if (count == 0) {
stg1_error_message("No NET device found."); stg1_error_message("No NET device found.");
i = ask_insmod(NETWORK_DEVICES); i = ask_insmod();
if (i == RETURN_BACK) if (i == RETURN_BACK)
return NULL; return NULL;
return interface_select(); return interface_select();

397
probing.c
View File

@ -33,10 +33,10 @@
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <libgen.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
// #include <sys/socket.h>
#include <net/if.h> #include <net/if.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/mount.h> #include <sys/mount.h>
@ -54,40 +54,6 @@ struct media_info {
enum media_type type; enum media_type type;
}; };
struct pci_module_map {
unsigned short vendor; /* PCI vendor id */
unsigned short device; /* PCI device id */
char * module; /* module to load */
struct pci_module_map * next;
};
struct usb_module_map {
unsigned short vendor; /* PCI vendor id */
unsigned short device; /* PCI device id */
char * module; /* module to load */
struct usb_module_map * next;
};
char *usb_hcd[] = {
"uhci-hcd",
"ohci-hcd",
"ehci-hcd",
};
#define HCD_NUM (sizeof(usb_hcd) / sizeof(char *))
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 #ifndef DISABLE_NETWORK
struct net_description_elem struct net_description_elem
{ {
@ -101,11 +67,6 @@ static char * net_intf_too_early_name[50]; /* for modules providing more than on
static int net_intf_too_early_number = 0; static int net_intf_too_early_number = 0;
static int net_intf_too_early_ptr = 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) void net_discovered_interface(char * intf_name)
{ {
if (!intf_descr_for_discover) { if (!intf_descr_for_discover) {
@ -128,336 +89,20 @@ void net_discovered_interface(char * intf_name)
char * get_net_intf_description(char * intf_name) char * get_net_intf_description(char * intf_name)
{ {
int i; char dev[SYSFS_PATH_MAX];
for (i = 0; i < net_descr_number ; i++) char drv[SYSFS_PATH_MAX];
if (!strcmp(net_descriptions[i].intf_name, intf_name)) ssize_t i;
return net_descriptions[i].intf_description;
snprintf(dev, SYSFS_PATH_MAX, "/sys/class/net/%s/device/driver", intf_name);
if ((i = readlink(dev, drv, SYSFS_PATH_MAX)) > 0) {
drv[i] = '\0';
return strdup(basename(drv));
} else {
return strdup("unknown"); return strdup("unknown");
}
} }
#endif #endif
static struct pci_module_map * get_pci_ids()
{
static struct pci_module_map * pcidb = NULL;
struct pci_module_map *new, *last = NULL;
char buf[50];
int v, d;
FILE *f;
if (pcidb) return pcidb;
log_message("loading pcimap file");
if (!(f = fopen("/modules/modules.map", "rb"))) {
log_message("couldn't open pcimap file");
return NULL;
}
while (3 == (fscanf(f, "%x %x %48s", &v, &d, buf))) {
new = (struct pci_module_map *)malloc(sizeof(*pcidb));
new->vendor = v;
new->device = d;
new->module = strdup(buf);
new->next = NULL;
if (!pcidb) {
pcidb = last = new;
} else {
last->next = new;
last = new;
}
}
fclose(f);
return pcidb;
}
/* forward */
static void probe_that_type(enum driver_type type);
/* ---- PCI probe ---------------------------------------------- */
static void pci_probe(enum driver_type type)
{
FILE * f;
int n;
char buf[200];
char devname[22];
u_int8_t devdata[48];
static int need_usb_hcd[HCD_NUM];
struct pci_module_map * pci_ids = NULL;
int that_class;
switch (type) {
case SCSI_ADAPTERS:
that_class = PCI_CLASS_STORAGE_SCSI << 8;
break;
case IDE_ADAPTERS:
that_class = PCI_CLASS_STORAGE_IDE << 8;
break;
case RAID_ADAPTERS:
that_class = PCI_CLASS_STORAGE_RAID << 8;
break;
case NETWORK_DEVICES:
that_class = PCI_CLASS_NETWORK_ETHERNET << 8;
break;
case BRIDGE_OTHER:
that_class = PCI_CLASS_BRIDGE_OTHER << 8;
break;
case USB_CONTROLLERS:
that_class = PCI_CLASS_SERIAL_USB << 8;
break;
default:
return;
}
if (NULL == (pci_ids = get_pci_ids())) {
log_message("PCI: could not get pci ids");
return;
}
if (!(f = fopen("/proc/bus/pci/devices", "r"))) {
log_message("PCI: could not open proc file");
return;
}
while (NULL != fgets(buf, sizeof(buf), f)) {
int i, fd, matched, dfn, vendor, device, class, subv, subid;
struct pci_module_map * pcidb;
sscanf(buf, "%x %x", &dfn, &vendor);
device = vendor & 0xFFFF; /* because scanf from dietlibc does not support %4f */
vendor = (vendor >> 16) & 0xFFFF;
snprintf(devname, sizeof(devname), "/proc/bus/pci/%02x/%02x.%x",
dfn >> 8, PCI_SLOT(dfn & 0xff), PCI_FUNC(dfn & 0xff));
log_message("gathering info for %s", devname);
if ((fd = open(devname, O_RDONLY)) != -1) {
i = read(fd, devdata, sizeof(devdata));
close(fd);
} else continue;
class = devdata[9] | (devdata[10] << 8) | (devdata[11] << 16);
subv = devdata[0x2c] | (devdata[0x2d] << 8);
subid = devdata[0x2e] | (devdata[0x2f] << 8);
if (that_class != (class & 0xffff00)) continue;
log_message("found pci device: %04x %04x %06x %04x %04x",
vendor, device, class, subv, subid);
for (matched = 0, pcidb = pci_ids; pcidb; pcidb = pcidb->next) {
if (pcidb->vendor == vendor && pcidb->device == device) {
/* vendor & device matched */
log_message("(pcimap) module is \"%s\"", pcidb->module);
if( get_param_valued("noload") && strstr(get_param_valued("noload"),pcidb->module)) {
log_message("not loading due to 'noload=' \"%s\"", pcidb->module);
continue;
}
#ifndef DISABLE_MEDIAS
if (type == IDE_ADAPTERS || type == SCSI_ADAPTERS || type == RAID_ADAPTERS) {
int wait_msg = 0;
enum insmod_return failed;
if (IS_AUTOMATIC) {
wait_message("Loading driver for storage adapter: %s", pcidb->module);
wait_msg = 1;
} else
stg1_info_message("About to load driver for storage adapter: %s", pcidb->module);
failed = my_insmod(pcidb->module, type, NULL);
if (wait_msg)
remove_wait_message();
warning_insmod_failed(failed);
}
#endif /* DISABLE_MEDIAS */
#ifndef DISABLE_NETWORK
if (type == NETWORK_DEVICES || type == BRIDGE_OTHER) {
int wait_msg = 0;
enum insmod_return failed;
if (IS_AUTOMATIC) {
wait_message("Loading driver for network device: %s", pcidb->module);
wait_msg = 1;
} else
stg1_info_message("About to load driver for network device: %s",
pcidb->module);
prepare_intf_descr(pcidb->module);
failed = my_insmod(pcidb->module, type, NULL);
if (wait_msg)
remove_wait_message();
warning_insmod_failed(failed);
if (intf_descr_for_discover) /* for modules providing more than one net intf */
net_discovered_interface(NULL);
}
#endif /* DISABLE_NETWORK */
if (type == USB_CONTROLLERS) {
/* found explicitly declared module */
for (i=0; i < HCD_NUM; i++) {
if(ptr_begins_static_str(pcidb->module, usb_hcd[i])) {
need_usb_hcd[i] = 1;
break;
}
}
}
matched = 1;
break;
}
} /* end of pcidb table */
#ifndef DISABLE_MEDIAS
if (!matched && type == IDE_ADAPTERS) {
/* probe ide-generic as last resort */
log_message("(guess) module is \"ide-generic\"");
int wait_msg = 0;
enum insmod_return failed;
if (IS_AUTOMATIC) {
wait_message("Loading driver for IDE adapter: ide-generic");
wait_msg = 1;
} else
stg1_info_message("About to load driver for IDE adapter: ide-generic");
failed = my_insmod("ide-generic", type, NULL);
if (wait_msg)
remove_wait_message();
warning_insmod_failed(failed);
}
#endif /* DISABLE_MEDIAS */
if (!matched && type == USB_CONTROLLERS && (class & 0xffff0f) == 0x0c0300) {
/* no module found, trying to identify one by class:
HCD: PCI Class:
uhci-hcd 0x000c0300
ohci-hcd 0x000c0310
ehci-hcd 0x000c0320
*/
log_message("(guess) module is \"%s\"", usb_hcd[(class & 0xf0)>>4]);
need_usb_hcd[(class & 0xf0)>>4] = 1;
}
} /* end of this vendor & device */
fclose(f);
/* load all usb controller modules now, starting from possible ehci-hcd */
/* to prevent case when old-timed module sitting on newer host controller */
if (type == USB_CONTROLLERS) {
enum insmod_return failed;
for (n=HCD_NUM-1; n >= 0; n--) {
if (need_usb_hcd[n]) {
/* do it AUTOMATIC -- for usb kbd case */
/* and ever silent
wait_message("Loading driver for USB controller: %s", usb_hcd[n]);
*/
failed = my_insmod(usb_hcd[n], USB_CONTROLLERS, NULL);
/*
remove_wait_message();
*/
warning_insmod_failed(failed);
}
}
}
}
/* ---- USB probe ---------------------------------------------- */
static void usb_probe(enum driver_type type)
{
static int already_probed_usb_controllers = 0;
static int already_mounted_usbdev = 0;
static int already_probed_hid = 0;
FILE * f;
char buf[200];
switch (type) {
#ifdef ENABLE_USBNET
case NETWORK_DEVICES:
#endif
case MEDIA_ADAPTERS:
case HID_DEVICES:
break;
default:
return;
}
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", "usbfs", 0, NULL)) {
log_message("USB: couldn't mount /proc/bus/usb");
return;
}
/* no need to show wait message -- we're doing this very first
wait_message("Waiting for USB stuff to show up.");
*/
sleep(2); /* sucking background work */
/*
remove_wait_message();
*/
}
/* dirty hacks */
if (type == MEDIA_ADAPTERS) {
stg1_info_message("About to load driver for usb storage device: usb-storage");
my_insmod("usb-storage", ANY_DRIVER_TYPE, NULL);
sleep(5); /* wait for dust settles down */
}
#ifdef ENABLE_USBNET
if (type == NETWORK_DEVICES) {
stg1_info_message("About to load driver for usb network device: usbnet");
my_insmod("usbnet", ANY_DRIVER_TYPE, NULL);
}
#endif
if (!(f = fopen("/proc/bus/usb/devices", "r"))) {
log_message("USB: could not open proc file");
return;
}
if (type == HID_DEVICES && !already_probed_hid) {
while (NULL != fgets(buf, sizeof(buf), f)) {
if (strstr(buf, "Cls=03")) {
my_insmod("usbhid", ANY_DRIVER_TYPE, NULL);
already_probed_hid = 1;
break;
}
}
}
fclose(f);
}
static void probe_that_type(enum driver_type type)
{
if (IS_EXPERT) {
ask_insmod(type);
return;
}
if (type == MEDIA_ADAPTERS) {
update_splash();
pci_probe(IDE_ADAPTERS);
update_splash();
pci_probe(SCSI_ADAPTERS);
update_splash();
pci_probe(RAID_ADAPTERS);
update_splash();
usb_probe(MEDIA_ADAPTERS);
update_splash();
} else {
update_splash();
pci_probe(type);
update_splash();
usb_probe(type);
update_splash();
}
}
#ifndef DISABLE_MEDIAS #ifndef DISABLE_MEDIAS
static struct media_info * medias = NULL; static struct media_info * medias = NULL;
@ -473,9 +118,7 @@ static void find_media(void)
char *s; char *s;
int count = 0; int count = 0;
if (!medias) if (medias)
probe_that_type(MEDIA_ADAPTERS);
else
free(medias); /* that does not free the strings, by the way */ free(medias); /* that does not free the strings, by the way */
if ((dir = opendir("/sys/block")) == NULL) { if ((dir = opendir("/sys/block")) == NULL) {
@ -601,13 +244,8 @@ void get_medias(enum media_type media, char *** names, char *** models)
} }
#endif /* DISABLE_MEDIAS */ #endif /* DISABLE_MEDIAS */
void probe_hiddev()
{
usb_probe(HID_DEVICES);
}
#ifndef DISABLE_NETWORK #ifndef DISABLE_NETWORK
int net_device_available(char * device) static int net_device_available(char * device)
{ {
struct ifreq req; struct ifreq req;
int s; int s;
@ -633,7 +271,6 @@ char ** get_net_devices(void)
char * devices[] = { char * devices[] = {
"eth0", "eth1", "eth2", "eth3", "eth4", "eth5", "eth0", "eth1", "eth2", "eth3", "eth4", "eth5",
"tr0", "tr0",
"plip0", "plip1", "plip2",
"fddi0", "fddi0",
#ifdef ENABLE_USBNET #ifdef ENABLE_USBNET
"usb0", "usb1", "usb2", "usb3", "usb0", "usb1", "usb2", "usb3",
@ -643,14 +280,6 @@ char ** get_net_devices(void)
char ** ptr = devices; char ** ptr = devices;
char * tmp[50]; char * tmp[50];
int i = 0; 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);
/* for some chipsets having nic in it, i.e. nForcex */
probe_that_type(BRIDGE_OTHER);
}
while (ptr && *ptr) { while (ptr && *ptr) {
if (net_device_available(*ptr)) if (net_device_available(*ptr))

View File

@ -24,40 +24,16 @@
enum media_type { CDROM, DISK, FLOPPY, TAPE, UNKNOWN_MEDIA }; enum media_type { CDROM, DISK, FLOPPY, TAPE, UNKNOWN_MEDIA };
enum driver_type { IDE_ADAPTERS, SCSI_ADAPTERS, RAID_ADAPTERS, MEDIA_ADAPTERS, NETWORK_DEVICES, HID_DEVICES, USB_CONTROLLERS, BRIDGE_OTHER, ANY_DRIVER_TYPE };
void get_medias(enum media_type media, char *** names, char *** models); void get_medias(enum media_type media, char *** names, char *** models);
void probe_hiddev(); void probe_hiddev();
char ** get_net_devices(void); char ** get_net_devices(void);
void net_discovered_interface(char * intf_name); void net_discovered_interface(char * intf_name);
char * get_net_intf_description(char * intf_name); char * get_net_intf_description(char * intf_name);
void prepare_intf_descr(const char * intf_descr);
#ifndef PCI_SLOT
#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
#endif
#ifndef PCI_FUNC
#define PCI_FUNC(devfn) ((devfn) & 0x07)
#endif
#ifndef SYSFS_PATH_MAX #ifndef SYSFS_PATH_MAX
#define SYSFS_PATH_MAX 256 #define SYSFS_PATH_MAX 256
#endif #endif
/*
* extract from linux/pci_ids.h
*/
#define PCI_BASE_CLASS_STORAGE 0x01
#define PCI_CLASS_STORAGE_SCSI 0x0100
#define PCI_CLASS_STORAGE_IDE 0x0101
#define PCI_CLASS_STORAGE_RAID 0x0104
#define PCI_CLASS_NETWORK_ETHERNET 0x0200
#define PCI_CLASS_SERIAL_FIREWIRE 0x0c00
#define PCI_CLASS_SERIAL_USB 0x0c03
#define PCI_CLASS_BRIDGE_OTHER 0x0680
/* /*
* from scsi/scsi.h * from scsi/scsi.h
*/ */

View File

@ -2,27 +2,27 @@
%def_with splash %def_with splash
Name: propagator Name: propagator
Version: 20070301 Version: 20080301
Release: alt7 Release: alt1
Summary: 'Early userspace' set of binaries Summary: 'Early userspace' set of binaries
License: GPL License: GPL
Group: System/Kernel and hardware Group: System/Kernel and hardware
Source0: %name-%version.tar.bz2 Source0: %name-%version-%release.tar
BuildRequires: mar >= 20070301-alt1 bzlib-devel-static libnewt-devel-static libslang-devel-static BuildRequires: libnewt-devel-static libslang-devel-static
BuildRequires: mkinitrd-busybox module-init-tools-initramfs udev-initramfs
%description %description
%name is a set of binaries useful in 'early userspace' environment, %name is a set of binaries useful in 'early userspace' environment,
including init and various helpers for hw probing and bootstrapping. including init and various helpers for hw probing and bootstrapping.
%prep %prep
%setup -c %setup
%build %build
make %{?_with_shell:WITH_SHELL=t} %{?_with_splash:WITH_SPLASH=t} \ make %{?_with_shell:WITH_SHELL=t} %{?_with_splash:WITH_SPLASH=t}
LIBDIR=%_libdir CFLAGS="$RPM_OPT_FLAGS -D_GNU_SOURCE"
%install %install
%make_install DESTDIR=%buildroot LIBDIR=%_libdir install %make_install DESTDIR=%buildroot LIBDIR=%_libdir install
@ -32,6 +32,9 @@ make %{?_with_shell:WITH_SHELL=t} %{?_with_splash:WITH_SPLASH=t} \
%_libdir/%name %_libdir/%name
%changelog %changelog
* Sat Mar 1 2008 Sergey Bolshakov <sbolshakov@altlinux.ru> 20080301-alt1
- use udev from now
* Wed Aug 8 2007 Sergey Bolshakov <sbolshakov@altlinux.ru> 20070301-alt7 * Wed Aug 8 2007 Sergey Bolshakov <sbolshakov@altlinux.ru> 20070301-alt7
- do not show %name build date on tty1, closes \#12491 - do not show %name build date on tty1, closes \#12491

111
stage1.c
View File

@ -47,10 +47,6 @@
#include "mount.h" #include "mount.h"
#include "insmod.h" #include "insmod.h"
#ifdef ENABLE_PCMCIA
#include "pcmcia/pcmcia.h"
#endif
#ifndef DISABLE_CDROM #ifndef DISABLE_CDROM
#include "cdrom.h" #include "cdrom.h"
#endif #endif
@ -180,65 +176,6 @@ static void spawn_splash(void)
#endif #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
}
/************************************************************ /************************************************************
*/ */
@ -258,7 +195,7 @@ static void expert_third_party_modules(void)
if (results != RETURN_OK) if (results != RETURN_OK)
return; return;
my_insmod("floppy", ANY_DRIVER_TYPE, NULL); my_insmod("floppy", NULL);
if (my_mount("/dev/fd0", floppy_mount_location, "ext2", 0) == -1) { 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."); stg1_error_message("I can't find a Linux ext2 floppy in first floppy drive.");
@ -298,27 +235,6 @@ static void expert_third_party_modules(void)
return expert_third_party_modules(); 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
}
/************************************************************ /************************************************************
*/ */
@ -405,20 +321,9 @@ void getversion()
int main(int argc, char **argv, char **env) int main(int argc, char **argv, char **env)
{ {
enum return_type ret; enum return_type ret;
char * pcmcia_adapter = NULL;
char buf[128]; char buf[128];
open_log(); open_log();
if (strstr(argv[0], "modprobe"))
{
if (argc == 4)
return(my_insmod(argv[argc-1], ANY_DRIVER_TYPE, NULL));
else
return(255);
}
spawn_interactive();
getversion(); getversion();
log_message("welcome to the %s install (alt-stage1, built " __DATE__ " " __TIME__")", version); log_message("welcome to the %s install (alt-stage1, built " __DATE__ " " __TIME__")", version);
process_cmdline(); process_cmdline();
@ -427,19 +332,8 @@ int main(int argc, char **argv, char **env)
spawn_splash(); spawn_splash();
prepare_progress(); prepare_progress();
update_splash(); update_splash();
init_modules_insmoding();
snprintf(buf, sizeof(buf), "Welcome to %s", version); snprintf(buf, sizeof(buf), "Welcome to %s", version);
init_frontend(buf); init_frontend(buf);
probe_hiddev();
if (IS_EXPERT)
expert_third_party_modules();
if (IS_UPDATEMODULES)
update_modules();
update_splash();
handle_pcmcia(&pcmcia_adapter);
update_splash(); update_splash();
if (IS_RESCUE && total_memory() < MEM_LIMIT_RESCUE) { if (IS_RESCUE && total_memory() < MEM_LIMIT_RESCUE) {
@ -460,9 +354,6 @@ int main(int argc, char **argv, char **env)
fatal_error("could not select an installation method"); fatal_error("could not select an installation method");
/* all went good */ /* all went good */
if (interactive_pid != 0)
kill(interactive_pid, 9);
if (shell_pid != 0) if (shell_pid != 0)
kill(shell_pid, 9); kill(shell_pid, 9);

10
tools.c
View File

@ -30,9 +30,9 @@
#include <stdio.h> #include <stdio.h>
#include <dirent.h> #include <dirent.h>
#include <sys/types.h> #include <sys/types.h>
#include <bzlib.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/poll.h> #include <sys/poll.h>
#include "stage1.h" #include "stage1.h"
#include "log.h" #include "log.h"
#include "mount.h" #include "mount.h"
@ -520,12 +520,12 @@ int string_array_length(char ** a)
int do_losetup(char * device, char * target) int do_losetup(char * device, char * target)
{ {
int loopfd, targfd; int i, loopfd, targfd;
struct loop_info loopInfo; struct loop_info loopInfo;
my_insmod("loop", ANY_DRIVER_TYPE, NULL); my_insmod("loop", NULL);
/* wait for udev's dust settles down */
loopfd = open( device, O_RDONLY ); for (i=3; i && (loopfd = open(device, O_RDONLY)) < 0; --i, sleep(1));
if ( loopfd < 0 ) if ( loopfd < 0 )
{ {
log_message( "losetup: error opening %s: %s", device, strerror(errno) ); log_message( "losetup: error opening %s: %s", device, strerror(errno) );