orphan
[debian/elilo] / elilo.c
1 /* 
2  * elilo.c - IA-64/IA-32/x86_64 EFI Linux loader
3  *
4  *  Copyright (C) 1999-2003 Hewlett-Packard Co.
5  *      Contributed by David Mosberger <davidm@hpl.hp.com>.
6  *      Contributed by Stephane Eranian <eranian@hpl.hp.com>
7  *
8  *  Copyright (C) 1999-2000 VA Linux Systems
9  *       Contributed by Johannes Erdfelt <jerdfelt@valinux.com>.
10  *
11  *  Copyright (C) 2006-2009 Intel Corporation
12  *      Contributed by Fenghua Yu <fenghua.yu@intel.com>
13  *      Contributed by Bibo Mao <bibo.mao@intel.com>
14  *      Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
15  *
16  * This file is part of the ELILO, the EFI Linux boot loader.
17  *
18  *  ELILO is free software; you can redistribute it and/or modify
19  *  it under the terms of the GNU General Public License as published by
20  *  the Free Software Foundation; either version 2, or (at your option)
21  *  any later version.
22  *
23  *  ELILO is distributed in the hope that it will be useful,
24  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
25  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  *  GNU General Public License for more details.
27  *
28  *  You should have received a copy of the GNU General Public License
29  *  along with ELILO; see the file COPYING.  If not, write to the Free
30  *  Software Foundation, 59 Temple Place - Suite 330, Boston, MA
31  *  02111-1307, USA.
32  *
33  * Please check out the elilo.txt for complete documentation on how
34  * to use this program.
35  */
36
37 #include <efi.h>
38 #include <efilib.h>
39
40 #include "elilo.h"
41 #include "vars.h"
42 #include "gzip.h"
43
44 #include "getopt.h"
45 #include "fileops.h"
46 #include "loader.h"
47 #include "config.h" /* for config_init() */
48
49 #define ELILO_SHARED_CMDLINE_OPTS       L"pPMC:aDhd:i:vVc:E"
50
51 elilo_config_t elilo_opt;
52
53 EFI_SYSTEM_TABLE *systab;       /* pointer to EFI system table */
54
55 extern INTN wait_timeout (UINTN);
56
57 /*
58  * Load the Linux kernel in memory from the boot media
59  * Output:
60  *      kd = address of kernel entry point
61  *         + end address of kernel code+data+bss
62  *         + kernel entry point
63  * Return:
64  *      ELILO_LOAD_ERROR   : if something went wrong
65  *      ELILO_LOAD_ABORTED : user interruption while loading
66  *      ELILO_LOAD_SUCCESS : otherwise
67  */
68 static INTN
69 do_kernel_load(CHAR16 *kname, kdesc_t *kd)
70 {
71         loader_ops_t    *ldops;
72         EFI_STATUS status;
73         fops_fd_t fd;
74
75         status = fops_open(kname, &fd);
76         if (EFI_ERROR(status)) {
77                 ERR_PRT((L"Kernel file  not found %s", kname));
78                 return ELILO_LOAD_ERROR;
79         }
80         fops_close(fd);
81
82         ldops = loader_probe(kname);
83         if (ldops == NULL) {
84                 ERR_PRT((L"Cannot find a loader for %s", kname));
85                 return ELILO_LOAD_ERROR;
86         }
87
88         VERB_PRT(1,Print(L"Using %s loader\n", ldops->ld_name));
89         
90         return ldops->ld_load_kernel(kname, kd);
91 }
92
93 INTN
94 kernel_load(EFI_HANDLE image, CHAR16 *kname, kdesc_t *kd, memdesc_t *imem, memdesc_t *mmem)
95 {
96         CHAR16 kernel[FILENAME_MAXLEN];
97
98         /*
99          * Do the vm image switch here
100          * if there is "vmm=" then elilo should load image specified
101          * in "vmm=" and then give the "image" to vmm as target kernel image
102          */
103         if (elilo_opt.vmcode[0])
104                 StrCpy(kernel, elilo_opt.vmcode);
105         else
106                 StrCpy(kernel, kname);
107         /*
108          * Now let's try to load the kernel !
109          */
110         switch(do_kernel_load(kernel, kd)) {
111                 case ELILO_LOAD_SUCCESS:
112                         break;
113
114                 case ELILO_LOAD_ERROR:
115                         /* XXX: add fallback support */
116                         return ELILO_LOAD_ERROR;
117                 
118                 case ELILO_LOAD_ABORTED:
119                         /* we drop initrd in case we aborted the load */
120                         elilo_opt.initrd[0] = CHAR_NULL;
121                         elilo_opt.vmcode[0] = CHAR_NULL;
122
123                         /* will go back to interactive selection */
124                         elilo_opt.prompt  = 1; 
125                         elilo_opt.timeout = ELILO_DEFAULT_TIMEOUT;
126                         elilo_opt.delay   = 0;
127
128                         return ELILO_LOAD_RETRY;        
129         }
130
131         VERB_PRT(3, Print(L"kernel loaded in [" PTR_FMT "-" PTR_FMT "] entry=" PTR_FMT "\n", 
132                           kd->kstart, kd->kend, kd->kentry));
133
134         if (elilo_opt.initrd[0]) {
135
136                 /* ramdisk image is moved to the top of available extended memory later by start_kernel() */
137                 if (sysdeps_initrd_get_addr(kd, imem) == -1) goto exit_error;
138
139                 switch(load_file(elilo_opt.initrd, imem)) {
140                         case ELILO_LOAD_SUCCESS:
141                                 break;
142                         case ELILO_LOAD_ERROR:
143                                 goto exit_error;
144                         case ELILO_LOAD_ABORTED:
145                                 free_kmem();
146                                 /* we drop initrd in case we aborted the load */
147                                 elilo_opt.initrd[0] = CHAR_NULL;
148                                 elilo_opt.vmcode[0] = CHAR_NULL;
149                                 elilo_opt.prompt    = 1; 
150                                 elilo_opt.timeout   = ELILO_DEFAULT_TIMEOUT;
151                                 elilo_opt.delay     = 0;
152
153                                 return ELILO_LOAD_RETRY;
154                 }
155         }
156
157         if (elilo_opt.vmcode[0]) {
158
159                 mmem->start_addr = 0; /* let the allocator decide */
160
161                 switch(load_file(kname, mmem)) {
162                         case ELILO_LOAD_SUCCESS:
163                                 break;
164                         case ELILO_LOAD_ERROR:
165                                 goto exit_error;
166                         case ELILO_LOAD_ABORTED:
167                                 if (imem->start_addr)
168                                         free(imem->start_addr);
169                                 free_kmem();
170                                 /* we drop initrd in case we aborted the load */
171                                 elilo_opt.initrd[0] = CHAR_NULL;
172                                 elilo_opt.vmcode[0] = CHAR_NULL;
173                                 elilo_opt.prompt    = 1; 
174                                 elilo_opt.timeout   = ELILO_DEFAULT_TIMEOUT;
175                                 elilo_opt.delay     = 0;
176
177                                 return ELILO_LOAD_RETRY;
178                 }
179
180                 /* Test for a compressed image and unzip if found */
181                 if (gzip_probe(mmem->start_addr, mmem->size) == 0 &&
182                     gunzip_image(mmem) != ELILO_LOAD_SUCCESS) {
183                         if (imem->start_addr)
184                                 free(imem->start_addr);
185                         free(mmem->start_addr);
186                         free_kmem();
187                         /* we drop initrd in case we aborted the load */
188                         elilo_opt.initrd[0] = CHAR_NULL;
189                         elilo_opt.vmcode[0] = CHAR_NULL;
190                         elilo_opt.prompt    = 1; 
191                         elilo_opt.timeout   = ELILO_DEFAULT_TIMEOUT;
192                         elilo_opt.delay     = 0;
193
194                         return ELILO_LOAD_RETRY;
195                 }
196         }
197         return ELILO_LOAD_SUCCESS;
198 exit_error:
199         free_kmem();
200         if (imem->start_addr) free(imem->start_addr);
201         if (mmem->start_addr) free(mmem->start_addr);
202
203         return ELILO_LOAD_ERROR;
204 }
205
206 static INTN
207 main_loop(EFI_HANDLE dev, CHAR16 **argv, INTN argc, INTN index, EFI_HANDLE image)
208 {
209         CHAR16 kname[FILENAME_MAXLEN];
210         CHAR16 cmdline_tmp[CMDLINE_MAXLEN];
211         CHAR16 cmdline[CMDLINE_MAXLEN];
212         VOID *bp;
213         UINTN cookie;
214         EFI_STATUS status = EFI_SUCCESS;
215         kdesc_t kd;
216         memdesc_t imem, mmem;
217         INTN r, retries=0;
218
219         /*
220          * First place where we potentially do system dependent
221          * operations. It is a one time opportunity before entering
222          * the main loop
223          */
224         if (sysdeps_preloop_actions(dev, argv, argc, index, image) == -1) return -1;
225
226         for(;;) {
227                 kname[0] = cmdline_tmp[0] = cmdline[0] = CHAR_NULL;
228                 imem.start_addr = 0; imem.pgcnt = 0; imem.size = 0;
229                 elilo_opt.sys_img_opts = NULL;
230
231                 if (kernel_chooser(argv, argc, index, kname, cmdline_tmp) == -1) goto exit_error;
232
233                 switch (kernel_load(image, kname, &kd, &imem, &mmem)) {
234                         case ELILO_LOAD_SUCCESS: 
235                                 goto do_launch;
236                         case ELILO_LOAD_ERROR:
237                                 goto exit_error;
238                         /* otherwise we retry ! */
239                 }
240         } 
241
242 do_launch:
243         r =subst_vars(cmdline_tmp, cmdline, CMDLINE_MAXLEN);
244
245         VERB_PRT(3, Print(L"final cmdline(%d): %s\n", r, cmdline));
246
247         /* Give user time to see the output before launch */
248         if (elilo_opt.debug || elilo_opt.verbose) {
249                 r = wait_timeout(150);
250         /* have to turn off all console output(except error output) now before final get_mmemap()
251          * call or it can cause the efi map key to change and the ExitBootSvc call to fail,
252          * forcing debug and verbose options off is the surest way to enforce this.
253          */
254                 elilo_opt.debug=0;
255                 elilo_opt.verbose=0; 
256         }
257
258         /* free resources associated with file accesses (before ExitBootServices) */
259         close_devices();
260
261         /* No console output permitted after create_boot_params()! */
262         if ((bp=create_boot_params(cmdline, &imem, &mmem, &cookie)) == 0) goto error;
263
264         /* terminate bootservices 
265         * efi ExitBootSvcs spec: *note, get_memmap is called by create_boot_params() 
266         * An EFI OS loader must ensure that it has the system's current memory map at the time 
267         * it calls ExitBootServices(). This is done by passing in the current memory map's 
268         * MapKey value as returned by GetMemoryMap(). Care must be taken to ensure that the 
269         * memory map does not change between these two calls. It is suggested that 
270         * GetMemoryMap()be called immediately before calling ExitBootServices(). */
271
272 retry:
273         status = uefi_call_wrapper(BS->ExitBootServices, 2, image, cookie);
274         if (EFI_ERROR(status)) 
275         {
276                 ERR_PRT((L"\nExitBootSvcs: failed, memory map has changed.\n"));
277                 if (retries < 2)
278                 {       
279                         ERR_PRT((L"Main_Loop: Retrying,... have to rebuild boot params"));
280                         retries++;
281                         free_boot_params(bp);
282                         if ((bp=create_boot_params(cmdline, &imem, &mmem, &cookie)) == 0) goto error;                   
283                         goto retry;
284                 } else {
285                         ERR_PRT((L"\nMain_Loop: tried ExitBootSvcs 3 times... retries exceeded.... giving up\n"));
286                         goto bad_exit;
287                 }
288         }
289
290
291         start_kernel(kd.kentry, bp);
292         /* NOT REACHED */
293
294         ERR_PRT((L"start_kernel() return !"));
295 bad_exit:       
296         /*
297          * we are still in BootService mode
298          */
299         ERR_PRT((L"ExitBootServices failed %r", status));
300 error:
301         free_kmem();
302         if (imem.start_addr) free(imem.start_addr);
303         if (mmem.start_addr) free(mmem.start_addr);
304         if (bp) free_boot_params(bp);
305 exit_error:
306         return ELILO_LOAD_ERROR;
307
308 }
309
310 static VOID
311 elilo_help(VOID)
312 {
313         
314         Print(L"-d secs   timeout in 10th of second before booting\n");
315         Print(L"-h        this help text\n");
316         Print(L"-V        print version\n");
317         Print(L"-v        verbose level(can appear multiple times)\n");
318         Print(L"-a        always check for alternate kernel image\n");
319         Print(L"-i file   load file as the initial ramdisk\n");
320         Print(L"-m file   load file as additional boot time vmm module\n");
321         Print(L"-C file   indicate the config file to use\n");
322         Print(L"-P        parse config file only (verify syntax)\n");
323         Print(L"-D        enable debug prints\n");
324         Print(L"-p        force interactive mode\n");
325         Print(L"-c name   image chooser to use\n");
326         Print(L"-E        do not force EDD30 variable\n");
327
328         sysdeps_print_cmdline_opts();
329
330         Print(L"\n");
331
332         print_config_options();
333 }
334
335 /*
336  * XXX: hack to work around a problem with EFI command line argument when booted
337  * from network. In this case, it looks like LoadOptions/LoadOptionsSize contain
338  * garbage
339  */
340 static CHAR16 *default_load_options;
341 static UINTN default_load_options_size;
342 static INTN done_fixups;
343
344 static VOID
345 fixupargs(EFI_LOADED_IMAGE *info)
346 {
347         EFI_STATUS status;
348         EFI_PXE_BASE_CODE *pxe;
349
350 #define FAKE_ELILONAME  L"elilo-forced"
351
352         status = uefi_call_wrapper(BS->HandleProtocol, 3, info->DeviceHandle, &PxeBaseCodeProtocol, (VOID **)&pxe);
353         if (EFI_ERROR(status)) return;
354
355         default_load_options      = info->LoadOptions;
356         default_load_options_size = info->LoadOptionsSize;
357
358         info->LoadOptions     = FAKE_ELILONAME;
359         info->LoadOptionsSize = StrLen(info->LoadOptions)*sizeof(CHAR16);
360
361         done_fixups = 1;
362 }
363
364 /*
365  * we restore the arguments in case we modified them just to make sure
366  * we don't confuse caller.
367  */
368 static VOID
369 unfixupargs(EFI_LOADED_IMAGE *info)
370 {
371         if (done_fixups == 0) return;
372
373         info->LoadOptions     = default_load_options;
374         info->LoadOptionsSize = default_load_options_size;
375 }
376
377
378 /*
379  * in order to get fully detailed EFI path names to devices, EDD3.0 specification must
380  * be turned on. On new versions of EFI, this is the default. An environment variable
381  * called EDD30 reflects the current settings. If true, then EDD3.0 is enabled 
382  * and device path names show the detailed device types. If false, then a default 
383  * generic name is used instead. This has some implications of ELILO's ability to 
384  * provide a better naming scheme for detected devices. If EDD3.0 is enabled
385  * then much more precise names can be used which makes it easy to use. 
386  * If EDD3.0 is nont enabled, ELILO will still work but will use very generic names
387  * for devices.
388  *
389  * ELILO will check the value of the variable. If not true, then it will force it to
390  * true. This will require a reboot for EFI to make use of the new value.
391  * Return:
392  *      EFI_SUCCESS: if variable is already true or was set to true
393  *      EFI error code: otherwise, like when could not forced variable or unrecognized variable content
394  */
395 #define EDD30_GUID \
396 {0x964e5b21, 0x6459, 0x11d2, { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b}}
397
398 #define EDD30_ATTR (EFI_VARIABLE_RUNTIME_ACCESS|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_NON_VOLATILE)
399
400 static EFI_GUID edd30_guid = EDD30_GUID;
401
402 static INTN
403 check_edd30(VOID)
404 {
405         EFI_STATUS      status;
406         UINTN           l = sizeof(BOOLEAN);
407         UINT8           bool = FALSE;
408         INTN            ret = -1;
409
410         status = uefi_call_wrapper(RT->GetVariable, 5, L"EDD30", &edd30_guid, NULL, &l, &bool);
411         if (status == EFI_BUFFER_TOO_SMALL || (bool != TRUE && bool != FALSE)) {
412                 ERR_PRT((L"Warning: EDD30 EFI variable is not boolean value: forcing it to TRUE"));
413                 return -1;
414         }
415         if (status == EFI_SUCCESS && bool == TRUE) {
416                 VERB_PRT(3, Print(L"EDD30 is TRUE\n"));
417                 elilo_opt.edd30_on = TRUE;
418                 ret = 0;
419         } else {
420                 VERB_PRT(4, 
421                         if (status != EFI_SUCCESS) {
422                                 Print(L"EDD30 EFI variable not defined\n");
423                         } else {
424                                 Print(L"EDD30 EFI variable is false\n");
425                         }
426                 );
427         }
428
429         return ret;
430 }
431
432 static INTN
433 force_edd30(VOID)
434 {
435         EFI_STATUS      status;
436         UINTN           l = sizeof(BOOLEAN);
437         UINT8           bool;
438
439         bool = TRUE;
440         status = uefi_call_wrapper(RT->SetVariable, 5, L"EDD30", &edd30_guid, EDD30_ATTR, l, &bool);
441         if (EFI_ERROR(status)) {
442                 ERR_PRT((L"can't set EDD30 variable: ignoring it"));
443                 return -1;
444         }
445
446         VERB_PRT(3, Print(L"EDD30 variable forced to TRUE. You should reboot to take advantage of EDD3.0.\n"));
447
448         return 0;
449 }
450
451 /*
452  * That's equivalent of main(): main entry point
453  */
454 EFI_STATUS
455 efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *system_tab)
456 {
457         CHAR16 *argv[MAX_ARGS];
458         CHAR16 optstring[MAX_ARGS];
459         EFI_LOADED_IMAGE *info;
460         EFI_STATUS status, ret = EFI_LOAD_ERROR;
461         INTN argc = 0, c;
462         INTN edd30_status, retry;
463         CHAR16 *ptr, *arglist = NULL;
464         BOOLEAN devices_initialized = FALSE;
465         CHAR16 dpath[FILENAME_MAXLEN];
466         CHAR16 *devpath;
467
468         elilo_opt.verbose=0;
469         elilo_opt.debug=0;
470
471         /* initialize global variable */
472         systab = system_tab;
473         
474         /* initialize EFI library */
475         InitializeLib(image, systab);
476         /*
477          * disable the platform watchdog timer if we go interactive
478          * XXX: we should reinstate it once we're done
479          * It seems like with PXE, the timer is set to a few minutes
480          * and sometimes triggers if we stay too long in interactive
481          * mode.
482          * XXX: clean this up !
483          */
484        uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0x0, 0, NULL);
485
486         /* initialize memory allocator */
487         if (alloc_init() == -1) return EFI_LOAD_ERROR;
488
489         status = uefi_call_wrapper(BS->HandleProtocol, 3, image, &LoadedImageProtocol, (VOID **) &info);
490         if (EFI_ERROR(status)) {
491                 ERR_PRT((L"image handle does not support LOADED_IMAGE protocol"));
492                 return EFI_LOAD_ERROR;
493         }
494
495         VERB_PRT(5,Print(L"Loaded at " PTR_FMT " size=%ld bytes code=%d data=%d\n", info->ImageBase, info->ImageSize, info->ImageCodeType, info->ImageDataType));
496         /*
497          * verify EDD3.0 status. Users may have to reboot 
498          */
499         edd30_status = check_edd30();
500
501         /*
502          * initialize configuration empire
503          */
504         if (config_init() == -1) goto do_exit;
505
506         /* 
507          * architecture-specific initializations
508          */
509         if (sysdeps_init(info->DeviceHandle) == -1) goto do_exit;
510         if (sysdeps_register_options() == -1) goto do_exit;
511
512         /*
513          * This may be required in case Elilo was booted with absolutely no arguments
514          * Elilo's logic is that just like normal Linux programs at least one argument
515          * (argv[0]) exists at all times and that it usually gives the name of the program
516          * (the command used to start it).
517         ERR_PRT((L"LoadOptions=%x OpenSize=%d", info->LoadOptions, info->LoadOptionsSize));
518          */
519
520         /*
521          * in case there is something wrong with the default boot_device
522          * we default to basic fixups and we need to force interactive
523          * mode to make sure the user has a chance of specifying a kernel
524          */
525         fixupargs(info);
526
527 #if 0
528         Print(L"LoadOptions=%x OpenSize=%d\n", info->LoadOptions, info->LoadOptionsSize);
529         { INTN i; for (i=0; i< info->LoadOptionsSize>>1; i++) Print(L"options[%d]=%d (%c)\n", i, ((CHAR16 *)info->LoadOptions)[i], ((CHAR16 *)info->LoadOptions)[i]); }
530 #endif
531
532         /*
533          * we must copy argument because argify modifies the string.
534          * This caused problems when arguments are coming from NVRAM
535          * as passed by the EFI boot manager
536          *
537          * We add an extra character to the buffer in case the LoadOptions is not 
538          * NULL terminated. The extra space will be used to ADD the extra terminator.
539          */
540         arglist = alloc(info->LoadOptionsSize+sizeof(CHAR16), EfiLoaderData);
541         if (arglist == NULL) {
542                 ERR_PRT((L"cannot copy argument list"));
543                 return EFI_OUT_OF_RESOURCES;
544         }
545         Memcpy(arglist, info->LoadOptions, info->LoadOptionsSize);
546
547         argc = argify(arglist,info->LoadOptionsSize, argv); 
548
549         StrCpy(optstring, ELILO_SHARED_CMDLINE_OPTS);
550         StrCat(optstring, sysdeps_get_cmdline_opts());
551
552         while ((c=Getopt(argc, argv, optstring)) != -1 ) {
553                 switch(c) {
554                         case 'a':
555                                 elilo_opt.alt_check = 1;
556                                 break;
557                         case 'D':
558                                 elilo_opt.debug = 1;
559                                 break;
560                         case 'p':
561                                 elilo_opt.prompt = 1;
562                                 break;
563                         case 'v':
564                                 elilo_opt.verbose++;
565                                 if (elilo_opt.verbose > 5) elilo_opt.verbose = 5;
566                                 break;
567                         case 'h':
568                                 elilo_help();
569                                 ret = EFI_SUCCESS;
570                                 goto do_exit;
571                         case 'd':
572                                 /*
573                                  * zero is a valid value here, so we use the delay-set to mark the
574                                  * fact that the user specified a value on cmdline. See config.c
575                                  */
576                                 elilo_opt.delay = Atoi(Optarg);
577                                 elilo_opt.delay_set = 1;
578                                 break;
579                         case 'E':
580                                 /* don't force EDD30 EFI variable if not already set */
581                                 elilo_opt.edd30_no_force = 1;
582                                 break;
583                         case 'i':
584                                 if (StrLen(Optarg) >= FILENAME_MAXLEN-1) {
585                                         Print(L"initrd filename is limited to %d characters\n", FILENAME_MAXLEN);
586                                         goto do_exit;
587                                 }
588                                 StrCpy(elilo_opt.initrd, Optarg);
589                                 break;
590                         case 'm':
591                                 if (StrLen(Optarg) >= FILENAME_MAXLEN-1) {
592                                         Print(L"vmm module filename is limited to %d characters\n", FILENAME_MAXLEN);
593                                         goto do_exit;
594                                 }
595                                 StrCpy(elilo_opt.vmcode, Optarg);
596                                 break;
597                         case 'C':
598                                 if (StrLen(Optarg) >= FILENAME_MAXLEN-1) {
599                                         Print(L"config filename is limited to %d characters\n", FILENAME_MAXLEN);
600                                         goto do_exit;
601                                 }
602                                 StrCpy(elilo_opt.config, Optarg);
603                                 break;
604                         case 'M': /* builtin debug tool */
605                                 { mmap_desc_t mdesc; 
606                                         if (get_memmap(&mdesc) == -1) {
607                                                 Print(L"Cannot get memory map\n");
608                                                 return EFI_LOAD_ERROR;
609                                         }
610                                         print_memmap(&mdesc);
611                                         ret = EFI_SUCCESS;
612                                         goto do_exit;
613                                 }
614                         case 'V':
615                                 Print(L"ELILO v%s for EFI/%a\n", ELILO_VERSION, ELILO_ARCH);
616                                 ret = EFI_SUCCESS;
617                                 goto do_exit;
618                         case 'P':
619                                 /* cmdline only option */
620                                 elilo_opt.parse_only =  1;
621                                 break;
622                         case 'c':
623                                 if (StrLen(Optarg) >= FILENAME_MAXLEN-1) {
624                                         Print(L"chooser name is limited to %d characters\n", FILENAME_MAXLEN);
625                                         goto do_exit;
626                                 }
627                                 StrCpy(elilo_opt.chooser, Optarg);
628                                 break;
629                         default:
630                                 /*
631                                  * try system dependent options before declaring error
632                                  */
633                                 if (sysdeps_getopt(c, Optind, Optarg) == 0) continue;
634
635                                 Print(L"Unknown option -%c\n", (CHAR16)c);
636                                 goto do_exit;
637                 }
638         }
639         DBG_PRT((L"Optind=%d optarg=" PTR_FMT " argc=%d", Optind, Optarg, argc));
640
641         /*
642          * we can't defer this phase any longer...
643          * Must be done after the elilo_opt are initialized (at least partially)
644          */
645         if (init_devices(info->DeviceHandle) == -1) goto do_exit;
646
647         devices_initialized = TRUE;
648
649         devpath = DevicePathToStr(info->FilePath);
650
651         /*
652          * set per fileops defaults files for configuration and kernel
653          */
654         fops_setdefaults(elilo_opt.default_configs, elilo_opt.default_kernel, FILENAME_MAXLEN, devpath);
655
656         /*
657          * XXX: won't be visible if verbose not required from command line
658          */
659         VERB_PRT(2,Print(L"Default config: %s\nDefault_kernel: %s\n",
660                         elilo_opt.default_configs[0].fname, elilo_opt.default_kernel));
661         /*
662          * use default config file if not specified by user
663          */
664         ptr = elilo_opt.config[0] == CHAR_NULL ?  (retry=1,elilo_opt.default_configs[0].fname) : (retry=0,elilo_opt.config);
665
666         /*
667          * parse config file (verbose becomes visible if set)
668          */
669         ret = read_config(ptr);
670         VERB_PRT(1,Print(L"read_config=%r\n", ret));
671
672         /* Only try the default config filenames if user did not specify a
673          * config filename on the command line */
674         if (elilo_opt.config[0] == CHAR_NULL) {
675                 while ((ret != EFI_SUCCESS) &&
676                        (retry < MAX_DEFAULT_CONFIGS) &&
677                        (elilo_opt.default_configs[retry].fname[0] != CHAR_NULL)) {
678
679                         ptr = elilo_opt.default_configs[retry].fname;
680                         ret = read_config(ptr);
681                         VERB_PRT(1,Print(L"read_config=%r\n", ret));
682                         retry += 1;
683                 }
684         }
685         /*
686          * when the config file is not found, we fail only if:
687          *      - the user did not specified interactive mode
688          *      - the user did not explicitely specify the config file
689          */
690         if (ret == EFI_NOT_FOUND || ret == EFI_TFTP_ERROR) {
691                 if (elilo_opt.prompt == 0 && elilo_opt.config[0] != CHAR_NULL) {
692                         Print(L"config file %s not found\n", ptr);
693                         goto do_exit;
694                 }
695                 fops_getdefault_path(dpath, FILENAME_MAXLEN);
696                 if (ret == EFI_TFTP_ERROR)
697                         Print(L"no config file found on TFTP server in %s\n", dpath);
698                 else
699                         Print(L"no config file found in %s\n", dpath);
700         }
701         /*
702          * stop if just doing parsing
703          */
704         if (elilo_opt.parse_only) {
705                 if (ret == EFI_SUCCESS)
706                         Print(L"Config file %s parsed successfully\n", ptr);
707                 goto do_exit;
708         }
709         /*
710          * if there was an error when parsing the config file, then
711          * we force interactive mode to give a chance to the user.
712          * We also clear the error. 
713          */
714         if (ret != EFI_SUCCESS) {
715                 Print(L"forcing interactive mode due to config file error(s)\n");
716                 elilo_opt.prompt = 1;
717         }
718         /*
719          * However, if the user specified a kernel on the command line
720          * then we don't go to interactive mode, even if there was an option in
721          * the config file telling us to do so.
722          */
723         if (argc > Optind) {
724             elilo_opt.prompt = 0;
725         }
726
727         /*
728          * If EDD30 EFI variable was not set to TRUE (or not defined), we
729          * we try to force it. This will take effect at the next reboot.
730          *
731          * Some controllers don't have EDD30 support, in this case forcing it 
732          * may cause problems, therefore we check the edd_no_force option
733          * before making the call.
734          */
735         if (edd30_status == -1 && elilo_opt.edd30_no_force == 0) {
736                 force_edd30();
737         }
738
739         ret = EFI_LOAD_ERROR;
740
741
742
743         /* set default timeout if going interactive */
744         if ((elilo_opt.prompt && elilo_opt.timeout == 0)) {
745                 elilo_opt.timeout = ELILO_DEFAULT_TIMEOUT;
746         }
747
748         /*
749          * which chooser we will use 
750          */
751         if (init_chooser(info->DeviceHandle) == -1) {
752                 ERR_PRT((L"Cannot find a decent chooser\n"));
753                 goto do_exit;
754         }
755
756         //if (elilo_opt.prompt == 0) VERB_PRT(1, print_devices());
757
758         main_loop(info->DeviceHandle, argv, argc, Optind, image);
759         /* should not return */
760 do_exit:
761         unfixupargs(info);
762
763         //if (arglist) free(arglist);
764
765         /* free all resources assiocated with file accesses */
766         if (devices_initialized) close_devices();
767
768         /* garbage collect all remaining allocations */
769         free_all_memory();
770
771         return ret;
772 }