root/tags/6.2-3/packages/initramfs/init.c

Revision 1719, 6.7 kB (checked in by alexander, 2 years ago)

Previously, due to a programming error (reuse of the loop variable
for other purpose inside the loop) the CD wouldn't find itself when booting
from /dev/hdd if /dev/hdb contained a wrong CD. This bug is now fixed.

Line 
1 /*
2    Init for the Official LFS LiveCD
3    Written by Jeremy Huntwork, 2005-09-16
4
5    This code sets up a directory structure for the CD in the initramfs,
6    finds and mounts the LFS LiveCD, mounts the root file system via the
7    squashfs file, overlays it all with unionfs and finally passes
8    control over to sysvinit to finish the boot process.
9 */
10
11 #include "init.h"
12
13
14 /* Devices to check for the LFS CD, could scan some stuff in /proc in a later version */
15 const char *devices[] =
16 {
17         "/dev/hda", "/dev/hdb", "/dev/hdc", "/dev/hdd", "/dev/hde", "/dev/hdf", "/dev/hdg", "/dev/hdh",
18         "/dev/sr0", "/dev/sr1", "/dev/sr2", "/dev/sr3", "/dev/sr4", "/dev/sr5", "/dev/sr6", "/dev/sr7",
19         NULL
20 };
21
22 const char *lfscd;
23
24 int mountlfscd(void);
25
26 int losetup(char * loop, char * file, int flags)
27 {
28         struct loop_info loopinfo;
29         int fd, ffd;
30        
31         memset(&loopinfo, 0, sizeof(loopinfo));
32
33         ffd = open(file, flags);
34         if (ffd<0) {
35                 printf("Failed to open the %s file: %s\n", file, strerror(errno));
36                 return(0);
37         }
38        
39         fd = open(loop, flags);
40         if (fd<0) {
41                 printf("Failed to open the loop device: %s\n", strerror(errno));
42                 return(0);
43         }
44
45         snprintf(loopinfo.lo_name, LO_NAME_SIZE, "%s", file);
46
47         loopinfo.lo_offset = 0;
48         loopinfo.lo_encrypt_key_size = 0;
49         loopinfo.lo_encrypt_type = LO_CRYPT_NONE;
50
51         if(ioctl(fd, LOOP_SET_FD, ffd) < 0) {
52                 printf("Failed to set up device: %s\n", strerror(errno));
53                 return(0);
54         }
55         close(ffd);
56
57         if(ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
58                 printf("Failed to set up device: %s\n", strerror(errno));
59                 (void) ioctl(fd, LOOP_CLR_FD, 0);
60                 close(fd);
61                 return(0);
62         }
63         close(fd);
64         return(1);
65 }
66
67 int main(int argc, char * argv[], char * envp[])
68 {
69         int i, overhead;
70         int fd;
71         struct dm_task * dmt;
72         int devsize;
73        
74         printf("Initramfs activated\n");
75
76         mkdir("/proc", 0755);
77         mount("proc", "/proc", "proc", 0, 0);
78        
79         mkdir(TMPFS, 0755);
80         if (mount("tmpfs", TMPFS, "tmpfs", 0, "size=90%") < 0) {
81                 printf("Failed to mount tmpfs: %s\n", strerror(errno));
82                 return (0);
83         }
84        
85         mkdir(CDROM_MOUNT, 0755);
86
87         printf("Searching for the CD named %s...\n", VOLUME_ID);
88
89         for (i=0;i<MAX_RETRIES;i++)
90         {
91                 if (mountlfscd())
92                         break;
93
94                 /* Failed to find any device with an LFS LiveCD */
95                 printf("I couldn't find an LFS LiveCD in any drive!!\n");
96                 printf("I'm going to wait 10 seconds and try again (Try %d/%d)\n", i, MAX_RETRIES);
97                 sleep(10);
98         }
99
100         if (i>=MAX_RETRIES)
101         {
102                 printf("I couldn't find an LFS LiveCD in any drive after %d retries!\n", MAX_RETRIES);
103                 reboot(RB_POWER_OFF);
104                 return(0);
105         }
106
107         /* If we're here, we have the LiveCD mounted and verifieid */
108        
109         /* Now, attempt to attach the root file to /dev/loop0 */
110
111         printf("Setting up the loopback devices...\n");
112        
113         losetup("/dev/loop0", ROOT_FILE, O_RDONLY);
114        
115         /* Create a sparse file for the second loop */
116        
117         fd = open("/dev/loop0", O_RDONLY);
118         ioctl(fd, BLKGETSIZE, &devsize);
119         close(fd);
120        
121         overhead = 0x1000 + devsize * 2;
122        
123         fd = open(OVERLAY, O_CREAT | O_WRONLY, 0600);
124         ftruncate(fd, devsize * 0x200ULL + overhead);
125         close(fd);
126        
127         losetup("/dev/loop1", OVERLAY, O_RDWR);
128        
129         /* Set up device-mapper */
130         dmt = dm_task_create(DM_DEVICE_CREATE);
131         dm_task_set_name(dmt, "lfs-cd");
132         dm_task_set_major(dmt, 254);
133         dm_task_set_minor(dmt, 0);
134         dm_task_add_target(dmt, 0, devsize,
135             "snapshot", "/dev/loop0 /dev/loop1 p 8");
136         dm_task_run(dmt);
137         dm_task_destroy(dmt);
138                                                        
139         printf("Mounting root filesystem...\n");
140         mkdir(ROOT, 0755);
141         i = mount("/dev/mapper/lfs-cd", ROOT, "ext2", 0, 0);
142         if (i<0) {
143                 printf("Failed to mount root fs: %s\n", strerror(errno));
144                 return(0);
145         }
146
147         /* Move the tmpfs to /dev/shm in the root fs */
148
149         mount("/.tmpfs", ROOT "/dev/shm", NULL, MS_MOVE, NULL);
150
151         /* Create a symlink for the CD drive to /dev/lfs-cd */
152
153         symlink(lfscd, ROOT "/dev/lfs-cd");
154
155
156         /* Remove the "/init" binary to free some RAM */
157         unlink ("/init");
158         umount2("/proc", 0);
159        
160         /* Chroot into the root fs */
161
162         chdir(ROOT);
163         mount(".", "/", NULL, MS_MOVE, NULL);
164
165         if ( chroot(".") || chdir("/") )
166                 return(0);
167        
168         /* We're done! Pass control to sysvinit. */
169
170         printf("Starting init...\n");
171        
172         /* FIXME: file descriptors still point to initramfs */
173         execve("/sbin/init", argv, envp);
174         printf("Failed to start init: %s :(\n", strerror(errno));
175
176         return(0);
177 }
178
179 /* This will look for and mount the LFS LiveCD, if found/mounted it'll return 1, otherwise 0 */
180 int mountlfscd(void)
181 {
182         struct iso_primary_descriptor pd;
183         int i;
184         int correct_cd;
185
186         for(i=0;devices[i]!=NULL;i++)
187         {
188                 int fd, status;
189                 const char *curdevice = devices[i];
190                 char buf[ISO_BLOCK_SIZE];
191
192                 /* Try to open CD drive to see if we can use it */
193                 fd = open(curdevice, O_RDONLY | O_NONBLOCK);
194                 if (fd<0)
195                 {
196                         /*
197                                 We'll get here if we can't open the device
198                                 (No such device, No such file or directory, etc, etc)
199                        
200                         printf("%s: open failed: %s\n", curdevice, strerror(errno)); */
201                         continue; /* On to the next device!! */
202                 }
203
204                 /* Try to see what the status of the CD drive is */
205                 status = ioctl(fd, CDROM_DRIVE_STATUS, 0);
206                 if (status<0)
207                 {
208                         /* We'll probably get here if we open a hard disk.
209                            No need to always print out this error. */
210                         /* printf("%s: ioctl failed: %s\n", curdevice, strerror(errno)); */
211                         close(fd);
212                         continue; /* On to the next device!! */
213                 }
214
215                 if (status != CDS_DISC_OK)
216                 {
217                         /* We'll probably get here if there's no CD in the drive */
218                         printf("%s: Drive not ready\n", curdevice);
219                         close(fd);
220                         continue; /* On to the next device!! */
221                 }
222
223                 /* If we're here, the cd drive seems to have a disc in it, and is okay!
224                    Now we'll try to match the Volume ID */
225
226                 lseek(fd, ISO_PD_BLOCK*ISO_BLOCK_SIZE, SEEK_SET);
227
228                 /* Read the ISO Block info and fill a struct with it */
229
230                 read(fd, buf, ISO_BLOCK_SIZE);
231                 memcpy( &pd, buf, sizeof(pd) );
232
233                 printf("%s: Volume ID is %s\n", curdevice, pd.volume_id);
234
235                 /* close(fd); */
236
237                 /* Compare the string in pd.volume_id with the VOLUME_ID
238                    generated by the livecd Makefiles */
239
240                 correct_cd = strncmp(VOLUME_ID, pd.volume_id, strlen(VOLUME_ID));
241                 if (correct_cd!=0) {
242                         printf("This is not the correct CD. Moving on...\n");
243                         close(fd);
244                         continue;
245                 }
246
247                 /* Try to mount the cd drive*/
248                 status = mount(curdevice, CDROM_MOUNT, CDROM_FSTYPE, MS_RDONLY, NULL);
249                 if (status<0)
250                 {
251                         printf("%s: mount failed: %s\n", curdevice, strerror(errno));
252                         close(fd);
253                         continue; /* On to the next device!! */
254                 }
255
256                 /* If we're here, we definitely have the LiveCD mounted at the mount point :) */
257
258
259                 memset(buf, 0, 32); /* Clear buffer so we don't have to check read's status */
260                 read(fd, buf, 10);
261                 close(fd);
262
263                 /* YAY! we have the LFS LiveCD mounted :) */
264                 printf("%s: LFS LiveCD Verified\n", curdevice);
265                 lfscd = curdevice;
266                 return(1);
267         }
268
269         /* Nuts, can't find an LFS LiveCD anywhere */
270
271         return(0);
272 }
Note: See TracBrowser for help on using the browser.