//----------------------------------------------------------------------------- // Copyright © 2001 - Philip Howard - All rights reserved, released under GPL // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //----------------------------------------------------------------------------- // package cdinit // program cdinit1 (cd initializer stage 1) // // description // This program is the stage 1 initializer for the cdinit package. The // initial ram disk will contain this program as /etc/init. The kernel // will unpack and mount the initial ramdisk and execute /etc/init as // PID 1 thus invoking cdinit1. // // 1. Make directory /tmpfs // 2. Mount a tmpfs filesystem as /tmpfs // 3. Make various directories in /tmpfs // 4. Make enough directories in / to operate with // 5. For each CDROM device number in list: // 5.1 Make device node /tmpfs/dev/bootcd // 5.2 Mount /tmpfs/dev/bootcd as /tmpfs/cdrom // 5.3 If mounted, execve("/tmpfs/cdrom/${ARCH}/boot/cdinit2",...) // 5.4 Unlink /dev/bootcd // // See description of cdinit2.c for continuation. //----------------------------------------------------------------------------- // author Philip Howard // email phil@ipal.org //----------------------------------------------------------------------------- #include "cdinit.h" //----------------------------------------------------------------------------- // Define list of devices to try to mount to find the CDROM. // This list is not complete. More CDROM types should be added. //----------------------------------------------------------------------------- static const dev_t cdrom_devices [] = { makedev(3,0), // hda makedev(3,64), // hdb makedev(22,0), // hdc makedev(22,64), // hdd #ifdef CDINIT_MANY_DEVS makedev(33,0), // hde makedev(33,64), // hdf makedev(34,0), // hdg makedev(34,64), // hdh #endif makedev(11,0), // scd0 makedev(11,1), // scd1 #ifdef CDINIT_MANY_DEVS makedev(11,2), // scd2 makedev(11,3), // scd3 makedev(11,4), // scd4 makedev(11,5), // scd5 makedev(11,6), // scd6 makedev(11,7), // scd7 #endif 0 }; //----------------------------------------------------------------------------- // Define list of directories to make in / in the specified order. These will // be made via /tmpfs before it is pivoted to root. //----------------------------------------------------------------------------- static char * rootdir_list [] = { "bin", "boot", "cdrom", "dev", "etc", "home", "lib", "mnt", "opt", "proc", "root", "sbin", "tmp", "usr", "var", NULL }; //----------------------------------------------------------------------------- // Define argument lists and environment for execve(). //----------------------------------------------------------------------------- static char * const cdinit2_command [] = { "/tmpfs/cdrom/" CDINIT_ARCH_NAME "/boot/cdinit2", NULL }; //----------------------------------------------------------------------------- // Define an environment for execve(). //----------------------------------------------------------------------------- static char * environment [] = { NULL }; //----------------------------------------------------------------------------- // Where to store trace info. //----------------------------------------------------------------------------- #ifdef CDINIT_TRACE static const char * trace [4]; #endif //----------------------------------------------------------------------------- // Include functions. //----------------------------------------------------------------------------- #include "write_string.c" #include "write_dec_ulong.c" #ifdef CDINIT_TRACE #include "write_dec_slong.c" #endif //----------------------------------------------------------------------------- // function main1 //----------------------------------------------------------------------------- static int main1 () { char * * ptr_ptr ; const dev_t * dev_ptr ; //-------------------------------------- // Make directories we need temporarily. //-------------------------------------- trace2( "mkdir", "/tmpfs" ); if ( mkdir( "/tmpfs", 0755 ) != 0 ) return 2; trace2( "mkdir", "/mnt" ); if ( mkdir( "/mnt", 0755 ) != 0 ) return 2; //-------------------------------------------------------- // Mount the tmpfs filesystem that will later become root. //-------------------------------------------------------- trace4( "umount"+1, "/tmpfs"+1, "/tmpfs", "/tmpfs"+1 ); if ( mount( "/tmpfs"+1, "/tmpfs", "/tmpfs"+1, MS_MGC_VAL, 0 ) != 0 ) return 4; //---------------------------------------------------------------- // Make the basic set of directories in the future root directory. //---------------------------------------------------------------- trace2( "chdir", "/tmpfs" ); if ( chdir( "/tmpfs" ) != 0 ) return 2; for ( ptr_ptr = rootdir_list; * ptr_ptr; ++ ptr_ptr ) { trace2( "mkdir", * ptr_ptr ); if ( mkdir( * ptr_ptr, 0755 ) != 0 ) return 2; } trace2( "chdir", "/" ); if ( chdir( "/" ) != 0 ) return 2; //---------------------------------------------------------- // Search for the boot CD by looking for the first CD that // can be mounted for which the stage 2 loader will execute. //---------------------------------------------------------- for ( dev_ptr = cdrom_devices; * dev_ptr; ++ dev_ptr ) { trace2( "mknod", "/tmpfs/dev/bootcd" ); if ( mknod( "/tmpfs/dev/bootcd", S_IFBLK + 0755, * dev_ptr ) != 0 ) return 2; if ( mount( "/tmpfs/dev/bootcd", "/tmpfs/cdrom", "iso9660", MS_MGC_VAL | MS_RDONLY, 0 ) == 0 ) { trace2( "execve", cdinit2_command[0] ); execve( cdinit2_command[0], cdinit2_command, environment ); trace2( "umount", "/tmpfs/cdrom" ); if ( umount( "/tmpfs/cdrom" ) != 0 ) return 2; } trace2( "unlink", "/tmpfs/dev/bootcd" ); if ( unlink( "/tmpfs/dev/bootcd" ) != 0 ) return 2; } trace1( "find CDROM and cdinit2" ); return 1; } //----------------------------------------------------------------------------- // Function _start is really the main function. //----------------------------------------------------------------------------- void _start () { int rc ; errno = 0; #if 1 write_string( 1, "\r" #ifdef CDINIT_COLOR "\033[33;1m" #endif "cdinit v" CDINIT_VERSION ", " "Copyright (C) 2001, Philip Howard, All rights reserved, See GPL" #ifdef CDINIT_COLOR "\033[0m" #endif "\n" ); #endif rc = main1(); #ifdef CDINIT_TRACE if ( rc != 0 ) { int i; write_string( 1, "Error " ); write_dec_slong( 1, (signed long) ( errno ) ); write_string( 1, " doing:" ); for ( i = 0; i < rc; ++ i ) { write_string( 1, " " ); write_string( 1, trace[i] ); } write_string( 1, "\n" ); } #endif write_string( 1, "halting ... \n\n\n\n\n\n" ); reboot( LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_HALT, NULL ); for (;;); }