diff options
author | Oliver Schinagl <oliver@schinagl.nl> | 2011-04-27 13:13:05 (GMT) |
---|---|---|
committer | Oliver Schinagl <oliver@schinagl.nl> | 2011-04-27 13:13:05 (GMT) |
commit | cb589e64ddfbc502e8b1189ec7253c43b42cd183 (patch) | |
tree | a45aa4df23db84c279f39bd2c894ecf6bada0289 /uClinux-2.4.31-uc0/init | |
parent | d53ae4b2067e5e7c4f5a0b9a234a89e0582c2e84 (diff) | |
download | openipcam-cb589e64ddfbc502e8b1189ec7253c43b42cd183.zip openipcam-cb589e64ddfbc502e8b1189ec7253c43b42cd183.tar.gz openipcam-cb589e64ddfbc502e8b1189ec7253c43b42cd183.tar.bz2 |
linux-2.4.31 with uCLinux uc0 pre-patched
Diffstat (limited to 'uClinux-2.4.31-uc0/init')
-rw-r--r-- | uClinux-2.4.31-uc0/init/do_mounts.c | 1073 | ||||
-rw-r--r-- | uClinux-2.4.31-uc0/init/main.c | 661 | ||||
-rw-r--r-- | uClinux-2.4.31-uc0/init/version.c | 26 |
3 files changed, 1760 insertions, 0 deletions
diff --git a/uClinux-2.4.31-uc0/init/do_mounts.c b/uClinux-2.4.31-uc0/init/do_mounts.c new file mode 100644 index 0000000..80fc990 --- /dev/null +++ b/uClinux-2.4.31-uc0/init/do_mounts.c @@ -0,0 +1,1073 @@ +#define __KERNEL_SYSCALLS__ +#include <linux/config.h> +#include <linux/slab.h> +#include <linux/devfs_fs_kernel.h> +#include <linux/unistd.h> +#include <linux/ctype.h> +#include <linux/blk.h> +#include <linux/fd.h> +#include <linux/tty.h> +#include <linux/init.h> + +#include <linux/nfs_fs.h> +#include <linux/nfs_fs_sb.h> +#include <linux/nfs_mount.h> +#include <linux/minix_fs.h> +#include <linux/ext2_fs.h> +#include <linux/romfs_fs.h> +#include <linux/cramfs_fs.h> + +#define BUILD_CRAMDISK + +extern int get_filesystem_list(char * buf); + +extern asmlinkage long sys_mount(char *dev_name, char *dir_name, char *type, + unsigned long flags, void *data); +extern asmlinkage long sys_mkdir(const char *name, int mode); +extern asmlinkage long sys_chdir(const char *name); +extern asmlinkage long sys_fchdir(int fd); +extern asmlinkage long sys_chroot(const char *name); +extern asmlinkage long sys_unlink(const char *name); +extern asmlinkage long sys_symlink(const char *old, const char *new); +extern asmlinkage long sys_mknod(const char *name, int mode, dev_t dev); +extern asmlinkage long sys_umount(char *name, int flags); +extern asmlinkage long sys_ioctl(int fd, int cmd, unsigned long arg); + +#ifdef CONFIG_BLK_DEV_INITRD +unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */ +static int __initdata mount_initrd = 1; + +static int __init no_initrd(char *str) +{ + mount_initrd = 0; + return 1; +} + +__setup("noinitrd", no_initrd); +#else +static int __initdata mount_initrd = 0; +#endif + +int __initdata rd_doload; /* 1 = load RAM disk, 0 = don't load */ + +int root_mountflags = MS_RDONLY | MS_VERBOSE; +static char root_device_name[64]; + +/* this is initialized in init/main.c */ +kdev_t ROOT_DEV; + +static int do_devfs = 0; + +static int __init load_ramdisk(char *str) +{ + rd_doload = simple_strtol(str,NULL,0) & 3; + return 1; +} +__setup("load_ramdisk=", load_ramdisk); + +static int __init readonly(char *str) +{ + if (*str) + return 0; + root_mountflags |= MS_RDONLY; + return 1; +} + +static int __init readwrite(char *str) +{ + if (*str) + return 0; + root_mountflags &= ~MS_RDONLY; + return 1; +} + +__setup("ro", readonly); +__setup("rw", readwrite); + +static struct dev_name_struct { + const char *name; + const int num; +} root_dev_names[] __initdata = { + { "nfs", MKDEV(NFS_MAJOR, NFS_MINOR) }, + { "hda", 0x0300 }, + { "hdb", 0x0340 }, + { "loop", 0x0700 }, + { "hdc", 0x1600 }, + { "hdd", 0x1640 }, + { "hde", 0x2100 }, + { "hdf", 0x2140 }, + { "hdg", 0x2200 }, + { "hdh", 0x2240 }, + { "hdi", 0x3800 }, + { "hdj", 0x3840 }, + { "hdk", 0x3900 }, + { "hdl", 0x3940 }, + { "hdm", 0x5800 }, + { "hdn", 0x5840 }, + { "hdo", 0x5900 }, + { "hdp", 0x5940 }, + { "hdq", 0x5A00 }, + { "hdr", 0x5A40 }, + { "hds", 0x5B00 }, + { "hdt", 0x5B40 }, + { "sda", 0x0800 }, + { "sdb", 0x0810 }, + { "sdc", 0x0820 }, + { "sdd", 0x0830 }, + { "sde", 0x0840 }, + { "sdf", 0x0850 }, + { "sdg", 0x0860 }, + { "sdh", 0x0870 }, + { "sdi", 0x0880 }, + { "sdj", 0x0890 }, + { "sdk", 0x08a0 }, + { "sdl", 0x08b0 }, + { "sdm", 0x08c0 }, + { "sdn", 0x08d0 }, + { "sdo", 0x08e0 }, + { "sdp", 0x08f0 }, + { "ada", 0x1c00 }, + { "adb", 0x1c10 }, + { "adc", 0x1c20 }, + { "add", 0x1c30 }, + { "ade", 0x1c40 }, + { "fd", 0x0200 }, + { "md", 0x0900 }, + { "xda", 0x0d00 }, + { "xdb", 0x0d40 }, + { "ram", 0x0100 }, + { "scd", 0x0b00 }, + { "mcd", 0x1700 }, + { "cdu535", 0x1800 }, + { "sonycd", 0x1800 }, + { "aztcd", 0x1d00 }, + { "cm206cd", 0x2000 }, + { "gscd", 0x1000 }, + { "sbpcd", 0x1900 }, + { "eda", 0x2400 }, + { "edb", 0x2440 }, + { "pda", 0x2d00 }, + { "pdb", 0x2d10 }, + { "pdc", 0x2d20 }, + { "pdd", 0x2d30 }, + { "pcd", 0x2e00 }, + { "pf", 0x2f00 }, + { "apblock", APBLOCK_MAJOR << 8}, + { "ddv", DDV_MAJOR << 8}, + { "jsfd", JSFD_MAJOR << 8}, +#if defined(CONFIG_ARCH_S390) + { "dasda", (DASD_MAJOR << MINORBITS) }, + { "dasdb", (DASD_MAJOR << MINORBITS) + (1 << 2) }, + { "dasdc", (DASD_MAJOR << MINORBITS) + (2 << 2) }, + { "dasdd", (DASD_MAJOR << MINORBITS) + (3 << 2) }, + { "dasde", (DASD_MAJOR << MINORBITS) + (4 << 2) }, + { "dasdf", (DASD_MAJOR << MINORBITS) + (5 << 2) }, + { "dasdg", (DASD_MAJOR << MINORBITS) + (6 << 2) }, + { "dasdh", (DASD_MAJOR << MINORBITS) + (7 << 2) }, +#endif + { "ida/c0d0p",0x4800 }, + { "ida/c0d1p",0x4810 }, + { "ida/c0d2p",0x4820 }, + { "ida/c0d3p",0x4830 }, + { "ida/c0d4p",0x4840 }, + { "ida/c0d5p",0x4850 }, + { "ida/c0d6p",0x4860 }, + { "ida/c0d7p",0x4870 }, + { "ida/c0d8p",0x4880 }, + { "ida/c0d9p",0x4890 }, + { "ida/c0d10p",0x48A0 }, + { "ida/c0d11p",0x48B0 }, + { "ida/c0d12p",0x48C0 }, + { "ida/c0d13p",0x48D0 }, + { "ida/c0d14p",0x48E0 }, + { "ida/c0d15p",0x48F0 }, + { "ida/c1d0p",0x4900 }, + { "ida/c2d0p",0x4A00 }, + { "ida/c3d0p",0x4B00 }, + { "ida/c4d0p",0x4C00 }, + { "ida/c5d0p",0x4D00 }, + { "ida/c6d0p",0x4E00 }, + { "ida/c7d0p",0x4F00 }, + { "cciss/c0d0p",0x6800 }, + { "cciss/c0d1p",0x6810 }, + { "cciss/c0d2p",0x6820 }, + { "cciss/c0d3p",0x6830 }, + { "cciss/c0d4p",0x6840 }, + { "cciss/c0d5p",0x6850 }, + { "cciss/c0d6p",0x6860 }, + { "cciss/c0d7p",0x6870 }, + { "cciss/c0d8p",0x6880 }, + { "cciss/c0d9p",0x6890 }, + { "cciss/c0d10p",0x68A0 }, + { "cciss/c0d11p",0x68B0 }, + { "cciss/c0d12p",0x68C0 }, + { "cciss/c0d13p",0x68D0 }, + { "cciss/c0d14p",0x68E0 }, + { "cciss/c0d15p",0x68F0 }, + { "cciss/c1d0p",0x6900 }, + { "cciss/c2d0p",0x6A00 }, + { "cciss/c3d0p",0x6B00 }, + { "cciss/c4d0p",0x6C00 }, + { "cciss/c5d0p",0x6D00 }, + { "cciss/c6d0p",0x6E00 }, + { "cciss/c7d0p",0x6F00 }, + { "ataraid/d0p",0x7200 }, + { "ataraid/d1p",0x7210 }, + { "ataraid/d2p",0x7220 }, + { "ataraid/d3p",0x7230 }, + { "ataraid/d4p",0x7240 }, + { "ataraid/d5p",0x7250 }, + { "ataraid/d6p",0x7260 }, + { "ataraid/d7p",0x7270 }, + { "ataraid/d8p",0x7280 }, + { "ataraid/d9p",0x7290 }, + { "ataraid/d10p",0x72A0 }, + { "ataraid/d11p",0x72B0 }, + { "ataraid/d12p",0x72C0 }, + { "ataraid/d13p",0x72D0 }, + { "ataraid/d14p",0x72E0 }, + { "ataraid/d15p",0x72F0 }, + { "rd/c0d0p",0x3000 }, + { "rd/c0d0p1",0x3001 }, + { "rd/c0d0p2",0x3002 }, + { "rd/c0d0p3",0x3003 }, + { "rd/c0d0p4",0x3004 }, + { "rd/c0d0p5",0x3005 }, + { "rd/c0d0p6",0x3006 }, + { "rd/c0d0p7",0x3007 }, + { "rd/c0d0p8",0x3008 }, + { "rd/c0d1p",0x3008 }, + { "rd/c0d1p1",0x3009 }, + { "rd/c0d1p2",0x300a }, + { "rd/c0d1p3",0x300b }, + { "rd/c0d1p4",0x300c }, + { "rd/c0d1p5",0x300d }, + { "rd/c0d1p6",0x300e }, + { "rd/c0d1p7",0x300f }, + { "rd/c0d1p8",0x3010 }, + { "nftla", 0x5d00 }, + { "nftlb", 0x5d10 }, + { "nftlc", 0x5d20 }, + { "nftld", 0x5d30 }, + { "ftla", 0x2c00 }, + { "ftlb", 0x2c08 }, + { "ftlc", 0x2c10 }, + { "ftld", 0x2c18 }, + { "mtdblock", 0x1f00 }, + { "nb", 0x2b00 }, + { NULL, 0 } +}; + +kdev_t __init name_to_kdev_t(char *line) +{ + int base = 0, offs; + char *end; + + if (strncmp(line,"/dev/",5) == 0) { + struct dev_name_struct *dev = root_dev_names; + line += 5; + do { + int len = strlen(dev->name); + if (strncmp(line,dev->name,len) == 0) { + line += len; + base = dev->num; + break; + } + dev++; + } while (dev->name); + } + offs = simple_strtoul(line, &end, base?10:16); + if (*end) + offs = 0; + return to_kdev_t(base + offs); +} + +static int __init root_dev_setup(char *line) +{ + int i; + char ch; + + ROOT_DEV = name_to_kdev_t(line); + memset (root_device_name, 0, sizeof root_device_name); + if (strncmp (line, "/dev/", 5) == 0) line += 5; + for (i = 0; i < sizeof root_device_name - 1; ++i) + { + ch = line[i]; + if ( isspace (ch) || (ch == ',') || (ch == '\0') ) break; + root_device_name[i] = ch; + } + return 1; +} + +__setup("root=", root_dev_setup); + +static char * __initdata root_mount_data; +static int __init root_data_setup(char *str) +{ + root_mount_data = str; + return 1; +} + +static char * __initdata root_fs_names; +static int __init fs_names_setup(char *str) +{ + root_fs_names = str; + return 1; +} + +__setup("rootflags=", root_data_setup); +__setup("rootfstype=", fs_names_setup); + +static void __init get_fs_names(char *page) +{ + char *s = page; + + if (root_fs_names) { + strcpy(page, root_fs_names); + while (*s++) { + if (s[-1] == ',') + s[-1] = '\0'; + } + } else { + int len = get_filesystem_list(page); + char *p, *next; + + page[len] = '\0'; + for (p = page-1; p; p = next) { + next = strchr(++p, '\n'); + if (*p++ != '\t') + continue; + while ((*s++ = *p++) != '\n') + ; + s[-1] = '\0'; + } + } + *s = '\0'; +} +static void __init mount_block_root(char *name, int flags) +{ + char *fs_names = __getname(); + char *p; + + get_fs_names(fs_names); +retry: + for (p = fs_names; *p; p += strlen(p)+1) { + int err = sys_mount(name, "/root", p, flags, root_mount_data); + switch (err) { + case 0: + goto out; + case -EACCES: + flags |= MS_RDONLY; + goto retry; + case -EINVAL: + case -EBUSY: + continue; + } + /* + * Allow the user to distinguish between failed open + * and bad superblock on root device. + */ + printk ("VFS: Cannot open root device \"%s\" or %s\n", + root_device_name, kdevname (ROOT_DEV)); + printk ("Please append a correct \"root=\" boot option\n"); + panic("VFS: Unable to mount root fs on %s", + kdevname(ROOT_DEV)); + } + panic("VFS: Unable to mount root fs on %s", kdevname(ROOT_DEV)); +out: + putname(fs_names); + sys_chdir("/root"); + ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev; + printk("VFS: Mounted root (%s filesystem)%s.\n", + current->fs->pwdmnt->mnt_sb->s_type->name, + (current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY) ? " readonly" : ""); +} + +#ifdef CONFIG_ROOT_NFS +static int __init mount_nfs_root(void) +{ + void *data = nfs_root_data(); + + if (data && sys_mount("/dev/root","/root","nfs",root_mountflags,data) == 0) + return 1; + return 0; +} +#endif + +static int __init create_dev(char *name, kdev_t dev, char *devfs_name) +{ + void *handle; + char path[64]; + int n; + + sys_unlink(name); + if (!do_devfs) + return sys_mknod(name, S_IFBLK|0600, kdev_t_to_nr(dev)); + + handle = devfs_find_handle(NULL, dev ? NULL : devfs_name, + MAJOR(dev), MINOR(dev), DEVFS_SPECIAL_BLK, 1); + if (!handle) + return -1; + n = devfs_generate_path(handle, path + 5, sizeof (path) - 5); + if (n < 0) + return -1; + return sys_symlink(path + n + 5, name); +} + +#if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD) +static void __init change_floppy(char *fmt, ...) +{ + struct termios termios; + char buf[80]; + char c; + int fd; + va_list args; + va_start(args, fmt); + vsprintf(buf, fmt, args); + va_end(args); + fd = open("/dev/root", O_RDWR | O_NDELAY, 0); + if (fd >= 0) { + sys_ioctl(fd, FDEJECT, 0); + close(fd); + } + printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf); + fd = open("/dev/console", O_RDWR, 0); + if (fd >= 0) { + sys_ioctl(fd, TCGETS, (long)&termios); + termios.c_lflag &= ~ICANON; + sys_ioctl(fd, TCSETSF, (long)&termios); + read(fd, &c, 1); + termios.c_lflag |= ICANON; + sys_ioctl(fd, TCSETSF, (long)&termios); + close(fd); + } +} +#endif + +#ifdef CONFIG_BLK_DEV_RAM + +int __initdata rd_prompt = 1; /* 1 = prompt for RAM disk, 0 = don't prompt */ + +static int __init prompt_ramdisk(char *str) +{ + rd_prompt = simple_strtol(str,NULL,0) & 1; + return 1; +} +__setup("prompt_ramdisk=", prompt_ramdisk); + +int __initdata rd_image_start; /* starting block # of image */ + +static int __init ramdisk_start_setup(char *str) +{ + rd_image_start = simple_strtol(str,NULL,0); + return 1; +} +__setup("ramdisk_start=", ramdisk_start_setup); + +static int __init crd_load(int in_fd, int out_fd); + +/* + * This routine tries to find a RAM disk image to load, and returns the + * number of blocks to read for a non-compressed image, 0 if the image + * is a compressed image, and -1 if an image with the right magic + * numbers could not be found. + * + * We currently check for the following magic numbers: + * minix + * ext2 + * romfs + * cramfs + * gzip + */ +static int __init +identify_ramdisk_image(int fd, int start_block) +{ + const int size = 512; + struct minix_super_block *minixsb; + struct ext2_super_block *ext2sb; + struct romfs_super_block *romfsb; + struct cramfs_super *cramfsb; + int nblocks = -1; + unsigned char *buf; + + buf = kmalloc(size, GFP_KERNEL); + if (buf == 0) + return -1; + + minixsb = (struct minix_super_block *) buf; + ext2sb = (struct ext2_super_block *) buf; + romfsb = (struct romfs_super_block *) buf; + cramfsb = (struct cramfs_super *) buf; + memset(buf, 0xe5, size); + + /* + * Read block 0 to test for gzipped kernel + */ + lseek(fd, start_block * BLOCK_SIZE, 0); + read(fd, buf, size); + + /* + * If it matches the gzip magic numbers, return -1 + */ + if (buf[0] == 037 && ((buf[1] == 0213) || (buf[1] == 0236))) { + printk(KERN_NOTICE + "RAMDISK: Compressed image found at block %d\n", + start_block); + nblocks = 0; + goto done; + } + + /* romfs is at block zero too */ + if (romfsb->word0 == ROMSB_WORD0 && + romfsb->word1 == ROMSB_WORD1) { + printk(KERN_NOTICE + "RAMDISK: romfs filesystem found at block %d\n", + start_block); + nblocks = (ntohl(romfsb->size)+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; + goto done; + } + + if (cramfsb->magic == CRAMFS_32(CRAMFS_MAGIC)) { + printk(KERN_NOTICE + "RAMDISK: cramfs filesystem found at block %d\n", + start_block); + nblocks = (CRAMFS_32(cramfsb->size) + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; + goto done; + } + + /* + * Read block 1 to test for minix and ext2 superblock + */ + lseek(fd, (start_block+1) * BLOCK_SIZE, 0); + read(fd, buf, size); + + /* Try minix */ + if (minixsb->s_magic == MINIX_SUPER_MAGIC || + minixsb->s_magic == MINIX_SUPER_MAGIC2) { + printk(KERN_NOTICE + "RAMDISK: Minix filesystem found at block %d\n", + start_block); + nblocks = minixsb->s_nzones << minixsb->s_log_zone_size; + goto done; + } + + /* Try ext2 */ + if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) { + printk(KERN_NOTICE + "RAMDISK: ext2 filesystem found at block %d\n", + start_block); + nblocks = le32_to_cpu(ext2sb->s_blocks_count); + goto done; + } + + printk(KERN_NOTICE + "RAMDISK: Couldn't find valid RAM disk image starting at %d.\n", + start_block); + +done: + lseek(fd, start_block * BLOCK_SIZE, 0); + kfree(buf); + return nblocks; +} +#endif + +static int __init rd_load_image(char *from) +{ + int res = 0; + +#ifdef CONFIG_BLK_DEV_RAM + int in_fd, out_fd; + unsigned long rd_blocks, devblocks; + int nblocks, i; + char *buf; + unsigned short rotate = 0; +#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES) + char rotator[4] = { '|' , '/' , '-' , '\\' }; +#endif + + out_fd = open("/dev/ram", O_RDWR, 0); + if (out_fd < 0) + goto out; + + in_fd = open(from, O_RDONLY, 0); + if (in_fd < 0) + goto noclose_input; + + nblocks = identify_ramdisk_image(in_fd, rd_image_start); + if (nblocks < 0) + goto done; + + if (nblocks == 0) { +#ifdef BUILD_CRAMDISK + if (crd_load(in_fd, out_fd) == 0) + goto successful_load; +#else + printk(KERN_NOTICE + "RAMDISK: Kernel does not support compressed " + "RAM disk images\n"); +#endif + goto done; + } + + /* + * NOTE NOTE: nblocks suppose that the blocksize is BLOCK_SIZE, so + * rd_load_image will work only with filesystem BLOCK_SIZE wide! + * So make sure to use 1k blocksize while generating ext2fs + * ramdisk-images. + */ + if (sys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0) + rd_blocks = 0; + else + rd_blocks >>= 1; + + if (nblocks > rd_blocks) { + printk("RAMDISK: image too big! (%d/%lu blocks)\n", + nblocks, rd_blocks); + goto done; + } + + /* + * OK, time to copy in the data + */ + buf = kmalloc(BLOCK_SIZE, GFP_KERNEL); + if (buf == 0) { + printk(KERN_ERR "RAMDISK: could not allocate buffer\n"); + goto done; + } + + if (sys_ioctl(in_fd, BLKGETSIZE, (unsigned long)&devblocks) < 0) + devblocks = 0; + else + devblocks >>= 1; + + if (strcmp(from, "/dev/initrd") == 0) + devblocks = nblocks; + + if (devblocks == 0) { + printk(KERN_ERR "RAMDISK: could not determine device size\n"); + goto done; + } + + printk(KERN_NOTICE "RAMDISK: Loading %d blocks [%ld disk%s] into ram disk... ", + nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : ""); + for (i=0; i < nblocks; i++) { + if (i && (i % devblocks == 0)) { + printk("done disk #%ld.\n", i/devblocks); + rotate = 0; + if (close(in_fd)) { + printk("Error closing the disk.\n"); + goto noclose_input; + } + change_floppy("disk #%d", i/devblocks+1); + in_fd = open(from, O_RDONLY, 0); + if (in_fd < 0) { + printk("Error opening disk.\n"); + goto noclose_input; + } + printk("Loading disk #%ld... ", i/devblocks+1); + } + read(in_fd, buf, BLOCK_SIZE); + write(out_fd, buf, BLOCK_SIZE); +#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES) + if (!(i % 16)) { + printk("%c\b", rotator[rotate & 0x3]); + rotate++; + } +#endif + } + printk("done.\n"); + kfree(buf); + +successful_load: + res = 1; +done: + close(in_fd); +noclose_input: + close(out_fd); +out: + sys_unlink("/dev/ram"); +#endif + return res; +} + +static int __init rd_load_disk(int n) +{ +#ifdef CONFIG_BLK_DEV_RAM + if (rd_prompt) + change_floppy("root floppy disk to be loaded into RAM disk"); + create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL); +#endif + return rd_load_image("/dev/root"); +} + +#ifdef CONFIG_DEVFS_FS + +static void __init convert_name(char *prefix, char *name, char *p, int part) +{ + int host, bus, target, lun; + char dest[64]; + char src[64]; + char *base = p - 1; + + /* Decode "c#b#t#u#" */ + if (*p++ != 'c') + return; + host = simple_strtol(p, &p, 10); + if (*p++ != 'b') + return; + bus = simple_strtol(p, &p, 10); + if (*p++ != 't') + return; + target = simple_strtol(p, &p, 10); + if (*p++ != 'u') + return; + lun = simple_strtol(p, &p, 10); + if (!part) + sprintf(dest, "%s/host%d/bus%d/target%d/lun%d", + prefix, host, bus, target, lun); + else if (*p++ == 'p') + sprintf(dest, "%s/host%d/bus%d/target%d/lun%d/part%s", + prefix, host, bus, target, lun, p); + else + sprintf(dest, "%s/host%d/bus%d/target%d/lun%d/disc", + prefix, host, bus, target, lun); + *base = '\0'; + sprintf(src, "/dev/%s", name); + sys_mkdir(src, 0755); + *base = '/'; + sprintf(src, "/dev/%s", name); + sys_symlink(dest, src); +} + +static void __init devfs_make_root(char *name) +{ + + if (!strncmp(name, "sd/", 3)) + convert_name("../scsi", name, name+3, 1); + else if (!strncmp(name, "sr/", 3)) + convert_name("../scsi", name, name+3, 0); + else if (!strncmp(name, "ide/hd/", 7)) + convert_name("..", name, name + 7, 1); + else if (!strncmp(name, "ide/cd/", 7)) + convert_name("..", name, name + 7, 0); +} +#else +static void __init devfs_make_root(char *name) +{ +} +#endif + +static void __init mount_root(void) +{ +#ifdef CONFIG_ROOT_NFS + if (MAJOR(ROOT_DEV) == NFS_MAJOR + && MINOR(ROOT_DEV) == NFS_MINOR) { + if (mount_nfs_root()) { + sys_chdir("/root"); + ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev; + printk("VFS: Mounted root (nfs filesystem).\n"); + return; + } + printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n"); + ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0); + } +#endif + devfs_make_root(root_device_name); + create_dev("/dev/root", ROOT_DEV, root_device_name); +#ifdef CONFIG_BLK_DEV_FD + if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { + /* rd_doload is 2 for a dual initrd/ramload setup */ + if (rd_doload==2) { + if (rd_load_disk(1)) { + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 1); + create_dev("/dev/root", ROOT_DEV, NULL); + } + } else + change_floppy("root floppy"); + } +#endif + mount_block_root("/dev/root", root_mountflags); +} + +#ifdef CONFIG_BLK_DEV_INITRD +static int old_fd, root_fd; +static int do_linuxrc(void * shell) +{ + static char *argv[] = { "linuxrc", NULL, }; + extern char * envp_init[]; + + close(old_fd); + close(root_fd); + close(0); + close(1); + close(2); + setsid(); + (void) open("/dev/console",O_RDWR,0); + (void) dup(0); + (void) dup(0); + return execve(shell, argv, envp_init); +} + +#endif + +static void __init handle_initrd(void) +{ +#ifdef CONFIG_BLK_DEV_INITRD + int ram0 = kdev_t_to_nr(MKDEV(RAMDISK_MAJOR,0)); + int error; + int i, pid; + + create_dev("/dev/root.old", ram0, NULL); + /* mount initrd on rootfs' /root */ + mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); + sys_mkdir("/old", 0700); + root_fd = open("/", 0, 0); + old_fd = open("/old", 0, 0); + /* move initrd over / and chdir/chroot in initrd root */ + sys_chdir("/root"); + sys_mount(".", "/", NULL, MS_MOVE, NULL); + sys_chroot("."); + mount_devfs_fs (); + + pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); + if (pid > 0) { + while (pid != wait(&i)) + yield(); + } + + /* move initrd to rootfs' /old */ + sys_fchdir(old_fd); + sys_mount("/", ".", NULL, MS_MOVE, NULL); + /* switch root and cwd back to / of rootfs */ + sys_fchdir(root_fd); + sys_chroot("."); + sys_umount("/old/dev", 0); + close(old_fd); + close(root_fd); + + if (real_root_dev == ram0) { + sys_chdir("/old"); + return; + } + + ROOT_DEV = real_root_dev; + mount_root(); + + printk(KERN_NOTICE "Trying to move old root to /initrd ... "); + error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL); + if (!error) + printk("okay\n"); + else { + int fd = open("/dev/root.old", O_RDWR, 0); + printk("failed\n"); + printk(KERN_NOTICE "Unmounting old root\n"); + sys_umount("/old", MNT_DETACH); + printk(KERN_NOTICE "Trying to free ramdisk memory ... "); + if (fd < 0) { + error = fd; + } else { + error = sys_ioctl(fd, BLKFLSBUF, 0); + close(fd); + } + printk(!error ? "okay\n" : "failed\n"); + } +#endif +} + +static int __init initrd_load(void) +{ +#ifdef CONFIG_BLK_DEV_INITRD + create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, 0), NULL); + create_dev("/dev/initrd", MKDEV(RAMDISK_MAJOR, INITRD_MINOR), NULL); +#endif + return rd_load_image("/dev/initrd"); +} + +/* + * Prepare the namespace - decide what/where to mount, load ramdisks, etc. + */ +void prepare_namespace(void) +{ + int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; +#ifdef CONFIG_ALL_PPC + extern void arch_discover_root(void); + arch_discover_root(); +#endif /* CONFIG_ALL_PPC */ +#ifdef CONFIG_BLK_DEV_INITRD + if (!initrd_start) + mount_initrd = 0; + real_root_dev = ROOT_DEV; +#endif + sys_mkdir("/dev", 0700); + sys_mkdir("/root", 0700); + sys_mknod("/dev/console", S_IFCHR|0600, MKDEV(TTYAUX_MAJOR, 1)); +#ifdef CONFIG_DEVFS_FS + sys_mount("devfs", "/dev", "devfs", 0, NULL); + do_devfs = 1; +#endif + + create_dev("/dev/root", ROOT_DEV, NULL); + if (mount_initrd) { + if (initrd_load() && ROOT_DEV != MKDEV(RAMDISK_MAJOR, 0)) { + handle_initrd(); + goto out; + } + } else if (is_floppy && rd_doload && rd_load_disk(0)) + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + mount_root(); +out: + sys_umount("/dev", 0); + sys_mount(".", "/", NULL, MS_MOVE, NULL); + sys_chroot("."); + mount_devfs_fs (); +} + +#ifdef CONFIG_BLK_DEV_RAM + +#if defined(BUILD_CRAMDISK) && defined(CONFIG_BLK_DEV_RAM) + +/* + * gzip declarations + */ + +#define OF(args) args + +#ifndef memzero +#define memzero(s, n) memset ((s), 0, (n)) +#endif + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +#define INBUFSIZ 4096 +#define WSIZE 0x8000 /* window size--must be a power of two, and */ + /* at least 32K for zip's deflate method */ + +static uch *inbuf; +static uch *window; + +static unsigned insize; /* valid bytes in inbuf */ +static unsigned inptr; /* index of next byte to be processed in inbuf */ +static unsigned outcnt; /* bytes in output buffer */ +static int exit_code; +static long bytes_out; +static int crd_infd, crd_outfd; + +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) + +/* Diagnostic functions (stubbed out) */ +#define Assert(cond,msg) +#define Trace(x) +#define Tracev(x) +#define Tracevv(x) +#define Tracec(c,x) +#define Tracecv(c,x) + +#define STATIC static + +static int fill_inbuf(void); +static void flush_window(void); +static void *malloc(int size); +static void free(void *where); +static void error(char *m); +static void gzip_mark(void **); +static void gzip_release(void **); + +#include "../lib/inflate.c" + +static void __init *malloc(int size) +{ + return kmalloc(size, GFP_KERNEL); +} + +static void __init free(void *where) +{ + kfree(where); +} + +static void __init gzip_mark(void **ptr) +{ +} + +static void __init gzip_release(void **ptr) +{ +} + + +/* =========================================================================== + * Fill the input buffer. This is called only when the buffer is empty + * and at least one byte is really needed. + */ +static int __init fill_inbuf(void) +{ + if (exit_code) return -1; + + insize = read(crd_infd, inbuf, INBUFSIZ); + if (insize == 0) return -1; + + inptr = 1; + + return inbuf[0]; +} + +/* =========================================================================== + * Write the output window window[0..outcnt-1] and update crc and bytes_out. + * (Used for the decompressed data only.) + */ +static void __init flush_window(void) +{ + ulg c = crc; /* temporary variable */ + unsigned n; + uch *in, ch; + + write(crd_outfd, window, outcnt); + in = window; + for (n = 0; n < outcnt; n++) { + ch = *in++; + c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); + } + crc = c; + bytes_out += (ulg)outcnt; + outcnt = 0; +} + +static void __init error(char *x) +{ + printk(KERN_ERR "%s", x); + exit_code = 1; +} + +static int __init crd_load(int in_fd, int out_fd) +{ + int result; + + insize = 0; /* valid bytes in inbuf */ + inptr = 0; /* index of next byte to be processed in inbuf */ + outcnt = 0; /* bytes in output buffer */ + exit_code = 0; + bytes_out = 0; + crc = (ulg)0xffffffffL; /* shift register contents */ + + crd_infd = in_fd; + crd_outfd = out_fd; + inbuf = kmalloc(INBUFSIZ, GFP_KERNEL); + if (inbuf == 0) { + printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n"); + return -1; + } + window = kmalloc(WSIZE, GFP_KERNEL); + if (window == 0) { + printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n"); + kfree(inbuf); + return -1; + } + makecrc(); + result = gunzip(); + kfree(inbuf); + kfree(window); + return result; +} + +#endif /* BUILD_CRAMDISK && CONFIG_BLK_DEV_RAM */ +#endif /* CONFIG_BLK_DEV_RAM */ diff --git a/uClinux-2.4.31-uc0/init/main.c b/uClinux-2.4.31-uc0/init/main.c new file mode 100644 index 0000000..2121088 --- /dev/null +++ b/uClinux-2.4.31-uc0/init/main.c @@ -0,0 +1,661 @@ +/* + * linux/init/main.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * GK 2/5/95 - Changed to support mounting root fs via NFS + * Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96 + * Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96 + * Simplified starting of init: Michael A. Griffith <grif@acm.org> + */ + +#define __KERNEL_SYSCALLS__ + +#include <linux/config.h> +#include <linux/proc_fs.h> +#include <linux/devfs_fs_kernel.h> +#include <linux/unistd.h> +#include <linux/string.h> +#include <linux/ctype.h> +#include <linux/delay.h> +#include <linux/utsname.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/smp_lock.h> +#include <linux/blk.h> +#include <linux/hdreg.h> +#include <linux/iobuf.h> +#include <linux/bootmem.h> +#include <linux/file.h> +#include <linux/tty.h> + +#include <asm/io.h> +#include <asm/bugs.h> + +#if defined(CONFIG_ARCH_S390) +#include <asm/s390mach.h> +#include <asm/ccwcache.h> +#endif + +#ifdef CONFIG_ACPI +#include <linux/acpi.h> +#endif + +#ifdef CONFIG_PCI +#include <linux/pci.h> +#endif + +#ifdef CONFIG_DIO +#include <linux/dio.h> +#endif + +#ifdef CONFIG_ZORRO +#include <linux/zorro.h> +#endif + +#ifdef CONFIG_MTRR +# include <asm/mtrr.h> +#endif + +#ifdef CONFIG_NUBUS +#include <linux/nubus.h> +#endif + +#ifdef CONFIG_ISAPNP +#include <linux/isapnp.h> +#endif + +#ifdef CONFIG_IRDA +extern int irda_proto_init(void); +extern int irda_device_init(void); +#endif + +#ifdef CONFIG_X86_LOCAL_APIC +#include <asm/smp.h> +#endif + +/* + * Versions of gcc older than that listed below may actually compile + * and link okay, but the end product can have subtle run time bugs. + * To avoid associated bogus bug reports, we flatly refuse to compile + * with a gcc that is known to be too old from the very beginning. + */ +#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 91) +#if !defined(CONFIG_V850E) && !defined(CONFIG_NIOS) +#error Sorry, your GCC is too old. It builds incorrect kernels. +#else +#warning Sorry, your GCC is too old. It builds incorrect kernels. +#endif +#endif + +#ifdef CONFIG_FRV +extern const char _stext[], _etext[]; +#else +extern const char _stext, _etext; +#endif +extern char linux_banner[]; + +static int init(void *); + +extern void init_IRQ(void); +extern void init_modules(void); +extern void sock_init(void); +extern void fork_init(unsigned long); +extern void mca_init(void); +extern void sbus_init(void); +extern void ppc_init(void); +extern void sysctl_init(void); +extern void signals_init(void); +extern int init_pcmcia_ds(void); + +extern void free_initmem(void); +#ifdef CONFIG_ACPI_BUS +extern void acpi_early_init(void); +#else +static inline void acpi_early_init(void) { } +#endif + +#ifdef CONFIG_TC +extern void tc_init(void); +#endif + +extern void ecard_init(void); + +#if defined(CONFIG_SYSVIPC) +extern void ipc_init(void); +#endif + +/* + * Boot command-line arguments + */ +#define MAX_INIT_ARGS 8 +#define MAX_INIT_ENVS 8 + +extern void time_init(void); +extern void softirq_init(void); + +int rows, cols; + +char *execute_command; + +static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, }; +char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; + +static int __init profile_setup(char *str) +{ + int par; + if (get_option(&str,&par)) prof_shift = par; + return 1; +} + +__setup("profile=", profile_setup); + +static int __init checksetup(char *line) +{ + struct kernel_param *p; + + p = __setup_start; + do { + int n = strlen(p->str); + if (!strncmp(line,p->str,n)) { + if (p->setup_func(line+n)) + return 1; + } + p++; + } while (p < __setup_end); + return 0; +} + +/* this should be approx 2 Bo*oMips to start (note initial shift), and will + still work even if initially too large, it will just take slightly longer */ +unsigned long loops_per_jiffy = (1<<12); + +/* This is the number of bits of precision for the loops_per_jiffy. Each + bit takes on average 1.5/HZ seconds. This (like the original) is a little + better than 1% */ +#define LPS_PREC 8 + +#ifndef CONFIG_FRV +void __init calibrate_delay(void) +{ + unsigned long ticks, loopbit; + int lps_precision = LPS_PREC; + +#ifdef FIXED_BOGOMIPS + int bogus; + +/* FIXED_BOGOMIPS converted to __delay units. */ +#define FIXED_LOOPS_PER_JIFFY (unsigned long)(FIXED_BOGOMIPS * (500000 / HZ)) + +/* The maximum error in FIXED_LOOPS_PER_JIFFY that we will tolerate. */ +#define FIXED_LPJ_TOLERANCE (unsigned long)(FIXED_LOOPS_PER_JIFFY * 0.10) + + /* Make sure fixed delay - T% is zero ticks. */ + ticks = jiffies; + while (ticks == jiffies) /* Synchronize with start of tick */ + /* nothing */; + ticks = jiffies; + __delay(FIXED_LOOPS_PER_JIFFY - FIXED_LPJ_TOLERANCE); + bogus = (jiffies != ticks); + + if (! bogus) { + /* Make sure fixed delay + T% is one tick. The delay here + is very short because we're actually continuing timing from + the tick synchronization above (we don't resynchronize). */ + __delay(2 * FIXED_LPJ_TOLERANCE); + bogus = (jiffies != ticks + 1); + } + + if (! bogus) { + /* Use the precomputed value. */ + loops_per_jiffy = FIXED_LOOPS_PER_JIFFY; + printk("Delay loop constant: %lu.%02lu BogoMIPS (precomputed)\n", + (unsigned long)FIXED_BOGOMIPS, + ((unsigned long)(FIXED_BOGOMIPS * 100)) % 100); + return; + } else { + printk("Precomputed BogoMIPS value (%lu.%02lu) inaccurate!\n", + (unsigned long)FIXED_BOGOMIPS, + ((unsigned long)(FIXED_BOGOMIPS * 100)) % 100); + /* ... and fall through to normal bogomips calculation. */ + } +#endif /* FIXED_BOGOMIPS */ + + loops_per_jiffy = (1<<12); + + printk("Calibrating delay loop... "); + while (loops_per_jiffy <<= 1) { + /* wait for "start of" clock tick */ + ticks = jiffies; + while (ticks == jiffies) + /* nothing */; + /* Go .. */ + ticks = jiffies; + __delay(loops_per_jiffy); + ticks = jiffies - ticks; + if (ticks) + break; + } + +/* Do a binary approximation to get loops_per_jiffy set to equal one clock + (up to lps_precision bits) */ + loops_per_jiffy >>= 1; + loopbit = loops_per_jiffy; + while ( lps_precision-- && (loopbit >>= 1) ) { + loops_per_jiffy |= loopbit; + ticks = jiffies; + while (ticks == jiffies); + ticks = jiffies; + __delay(loops_per_jiffy); + if (jiffies != ticks) /* longer than 1 tick */ + loops_per_jiffy &= ~loopbit; + } + +/* Round the value and print it */ + printk("%lu.%02lu BogoMIPS\n", + loops_per_jiffy/(500000/HZ), + (loops_per_jiffy/(5000/HZ)) % 100); +} +#endif + +static int __init debug_kernel(char *str) +{ + if (*str) + return 0; + console_loglevel = 10; + return 1; +} + +static int __init quiet_kernel(char *str) +{ + if (*str) + return 0; + console_loglevel = 4; + return 1; +} + +__setup("debug", debug_kernel); +__setup("quiet", quiet_kernel); + +/* + * This is a simple kernel command line parsing function: it parses + * the command line, and fills in the arguments/environment to init + * as appropriate. Any cmd-line option is taken to be an environment + * variable if it contains the character '='. + * + * This routine also checks for options meant for the kernel. + * These options are not given to init - they are for internal kernel use only. + */ +static void __init parse_options(char *line) +{ + char *next,*quote; + int args, envs; + + if (!*line) + return; + args = 0; + envs = 1; /* TERM is set to 'linux' by default */ + next = line; + while ((line = next) != NULL) { + quote = strchr(line,'"'); + next = strchr(line, ' '); + while (next != NULL && quote != NULL && quote < next) { + /* we found a left quote before the next blank + * now we have to find the matching right quote + */ + next = strchr(quote+1, '"'); + if (next != NULL) { + quote = strchr(next+1, '"'); + next = strchr(next+1, ' '); + } + } + if (next != NULL) + *next++ = 0; + if (!strncmp(line,"init=",5)) { + line += 5; + execute_command = line; + /* In case LILO is going to boot us with default command line, + * it prepends "auto" before the whole cmdline which makes + * the shell think it should execute a script with such name. + * So we ignore all arguments entered _before_ init=... [MJ] + */ + args = 0; + continue; + } + if (checksetup(line)) + continue; + + /* + * Then check if it's an environment variable or + * an option. + */ + if (strchr(line,'=')) { + if (envs >= MAX_INIT_ENVS) + break; + envp_init[++envs] = line; + } else { + if (args >= MAX_INIT_ARGS) + break; + if (*line) + argv_init[++args] = line; + } + } + argv_init[args+1] = NULL; + envp_init[envs+1] = NULL; +} + + +extern void setup_arch(char **); +extern void cpu_idle(void); + +unsigned long wait_init_idle; + +#ifndef CONFIG_SMP + +#ifdef CONFIG_X86_LOCAL_APIC +static void __init smp_init(void) +{ + APIC_init_uniprocessor(); +} +#else +#define smp_init() do { } while (0) +#endif + +#else + + +/* Called by boot processor to activate the rest. */ +static void __init smp_init(void) +{ + /* Get other processors into their bootup holding patterns. */ + smp_boot_cpus(); + wait_init_idle = cpu_online_map; + clear_bit(current->processor, &wait_init_idle); /* Don't wait on me! */ + + smp_threads_ready=1; + smp_commence(); + + /* Wait for the other cpus to set up their idle processes */ + printk("Waiting on wait_init_idle (map = 0x%lx)\n", wait_init_idle); + while (wait_init_idle) { + cpu_relax(); + barrier(); + } + printk("All processors have done init_idle\n"); +} + +#endif + +/* + * We need to finalize in a non-__init function or else race conditions + * between the root thread and the init thread may cause start_kernel to + * be reaped by free_initmem before the root thread has proceeded to + * cpu_idle. + */ + +static void rest_init(void) +{ + kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL); + unlock_kernel(); + current->need_resched = 1; + cpu_idle(); +} + +/* + * Activate the first processor. + */ + +asmlinkage void __init start_kernel(void) +{ + char * command_line; + extern char saved_command_line[]; + +/* + * Interrupts are still disabled. Do necessary setups, then + * enable them + */ + lock_kernel(); + printk(linux_banner); + setup_arch(&command_line); + printk("Kernel command line: %s\n", saved_command_line); + parse_options(command_line); + trap_init(); + init_IRQ(); + sched_init(); + softirq_init(); + time_init(); + + /* + * HACK ALERT! This is early. We're enabling the console before + * we've done PCI setups etc, and console_init() must be aware of + * this. But we do want output early, in case something goes wrong. + */ + console_init(); +#ifdef CONFIG_MODULES + init_modules(); +#endif + if (prof_shift) { + unsigned int size; + /* only text is profiled */ + prof_len = (unsigned long) &_etext - (unsigned long) &_stext; + prof_len >>= prof_shift; + + size = prof_len * sizeof(unsigned int) + PAGE_SIZE-1; + prof_buffer = (unsigned int *) alloc_bootmem(size); + } + + kmem_cache_init(); + sti(); + calibrate_delay(); +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start && !initrd_below_start_ok && + initrd_start < min_low_pfn << PAGE_SHIFT) { + printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - " + "disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT); + initrd_start = 0; + } +#endif + mem_init(); + kmem_cache_sizes_init(); + pgtable_cache_init(); + + /* + * For architectures that have highmem, num_mappedpages represents + * the amount of memory the kernel can use. For other architectures + * it's the same as the total pages. We need both numbers because + * some subsystems need to initialize based on how much memory the + * kernel can use. + */ + if (num_mappedpages == 0) + num_mappedpages = num_physpages; + + fork_init(num_mappedpages); + proc_caches_init(); + vfs_caches_init(num_physpages); + buffer_init(num_physpages); + page_cache_init(num_physpages); +#if defined(CONFIG_ARCH_S390) + ccwcache_init(); +#endif + signals_init(); +#ifdef CONFIG_PROC_FS + proc_root_init(); +#endif + check_bugs(); + acpi_early_init(); /* before LAPIC and SMP init */ + printk("POSIX conformance testing by UNIFIX\n"); + + /* + * We count on the initial thread going ok + * Like idlers init is an unlocked kernel thread, which will + * make syscalls (and thus be locked). + */ + smp_init(); +#if defined(CONFIG_SYSVIPC) + ipc_init(); +#endif + rest_init(); +} + +struct task_struct *child_reaper = &init_task; + +static void __init do_initcalls(void) +{ + initcall_t *call; + + call = __initcall_start; + do { + (*call)(); + call++; + } while (call < __initcall_end); + + /* Make sure there is no pending stuff from the initcall sequence */ + flush_scheduled_tasks(); +} + +/* + * Ok, the machine is now initialized. None of the devices + * have been touched yet, but the CPU subsystem is up and + * running, and memory and process management works. + * + * Now we can finally start doing some real work.. + */ +static void __init do_basic_setup(void) +{ + + /* + * Tell the world that we're going to be the grim + * reaper of innocent orphaned children. + * + * We don't want people to have to make incorrect + * assumptions about where in the task array this + * can be found. + */ + child_reaper = current; + +#if defined(CONFIG_MTRR) /* Do this after SMP initialization */ +/* + * We should probably create some architecture-dependent "fixup after + * everything is up" style function where this would belong better + * than in init/main.c.. + */ + mtrr_init(); +#endif + +#ifdef CONFIG_SYSCTL + sysctl_init(); +#endif + + /* + * Ok, at this point all CPU's should be initialized, so + * we can start looking into devices.. + */ +#if defined(CONFIG_ARCH_S390) + s390_init_machine_check(); +#endif +#ifdef CONFIG_ACPI_INTERPRETER + acpi_init(); +#endif +#ifdef CONFIG_PCI + pci_init(); +#endif +#ifdef CONFIG_SBUS + sbus_init(); +#endif +#if defined(CONFIG_PPC) + ppc_init(); +#endif +#ifdef CONFIG_MCA + mca_init(); +#endif +#ifdef CONFIG_ARCH_ACORN + ecard_init(); +#endif +#ifdef CONFIG_ZORRO + zorro_init(); +#endif +#ifdef CONFIG_DIO + dio_init(); +#endif +#ifdef CONFIG_NUBUS + nubus_init(); +#endif +#ifdef CONFIG_ISAPNP + isapnp_init(); +#endif +#ifdef CONFIG_TC + tc_init(); +#endif + + /* Networking initialization needs a process context */ + sock_init(); + + start_context_thread(); + do_initcalls(); + +#ifdef CONFIG_IRDA + irda_proto_init(); + irda_device_init(); /* Must be done after protocol initialization */ +#endif +#ifdef CONFIG_PCMCIA + init_pcmcia_ds(); /* Do this last */ +#endif +} + +static void run_init_process(char *init_filename) +{ + argv_init[0] = init_filename; + execve(init_filename, argv_init, envp_init); +} + +extern void prepare_namespace(void); + +static int init(void * unused) +{ + struct files_struct *files; + lock_kernel(); + do_basic_setup(); + + prepare_namespace(); + + /* + * Ok, we have completed the initial bootup, and + * we're essentially up and running. Get rid of the + * initmem segments and start the user-mode stuff.. + */ + free_initmem(); + unlock_kernel(); + + /* + * Right now we are a thread sharing with a ton of kernel + * stuff. We don't want to end up in user space in that state + */ + + files = current->files; + if(unshare_files()) + panic("unshare"); + put_files_struct(files); + + if (open("/dev/console", O_RDWR, 0) < 0) + printk("Warning: unable to open an initial console.\n"); + + (void) dup(0); + (void) dup(0); + + /* + * We try each of these until one succeeds. + * + * The Bourne shell can be used instead of init if we are + * trying to recover a really broken machine. + */ + + if (execute_command) + run_init_process(execute_command); + + run_init_process("/sbin/init"); + run_init_process("/etc/init"); + run_init_process("/bin/init"); + run_init_process("/bin/sh"); + + panic("No init found. Try passing init= option to kernel."); +} diff --git a/uClinux-2.4.31-uc0/init/version.c b/uClinux-2.4.31-uc0/init/version.c new file mode 100644 index 0000000..ee0eff7 --- /dev/null +++ b/uClinux-2.4.31-uc0/init/version.c @@ -0,0 +1,26 @@ +/* + * linux/init/version.c + * + * Copyright (C) 1992 Theodore Ts'o + * + * May be freely distributed as part of Linux. + */ + +#include <linux/uts.h> +#include <linux/utsname.h> +#include <linux/version.h> +#include <linux/compile.h> + +#define version(a) Version_ ## a +#define version_string(a) version(a) + +int version_string(LINUX_VERSION_CODE); + +struct new_utsname system_utsname = { + UTS_SYSNAME, UTS_NODENAME, UTS_RELEASE, UTS_VERSION, + UTS_MACHINE, UTS_DOMAINNAME +}; + +const char linux_banner[] = + "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" + LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n"; |