1 /* ----------------------------------------------------------------------- *
3 * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
4 * Copyright 2009 Intel Corporation; author: H. Peter Anvin
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation
8 * files (the "Software"), to deal in the Software without
9 * restriction, including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense, and/or
11 * sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following
15 * The above copyright notice and this permission notice shall
16 * be included in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
27 * ----------------------------------------------------------------------- */
32 * Sample module to load Linux kernels. This module can also create
33 * a file out of the DHCP return data if running under PXELINUX.
35 * If -dhcpinfo is specified, the DHCP info is written into the file
36 * /dhcpinfo.dat in the initramfs.
38 * Usage: linux.c32 [-dhcpinfo] kernel arguments...
46 #include <syslinux/loadfile.h>
47 #include <syslinux/linux.h>
48 #include <syslinux/pxe.h>
50 const char *progname
= "linux.c32";
52 /* Find the last instance of a particular command line argument
53 (which should include the final =; do not use for boolean arguments) */
54 static char *find_argument(char **argv
, const char *argument
)
56 int la
= strlen(argument
);
60 for (arg
= argv
; *arg
; arg
++) {
61 if (!memcmp(*arg
, argument
, la
))
68 /* Search for a boolean argument; return its position, or 0 if not present */
69 static int find_boolean(char **argv
, const char *argument
)
73 for (arg
= argv
; *arg
; arg
++) {
74 if (!strcmp(*arg
, argument
))
75 return (arg
- argv
) + 1;
81 /* Stitch together the command line from a set of argv's */
82 static char *make_cmdline(char **argv
)
88 bytes
= 1; /* Just in case we have a zero-entry cmdline */
89 for (arg
= argv
; *arg
; arg
++) {
90 bytes
+= strlen(*arg
) + 1;
93 p
= cmdline
= malloc(bytes
);
97 for (arg
= argv
; *arg
; arg
++) {
98 int len
= strlen(*arg
);
105 p
--; /* Remove the last space */
111 int main(int argc
, char *argv
[])
113 const char *kernel_name
;
114 struct initramfs
*initramfs
;
119 bool opt_dhcpinfo
= false;
120 bool opt_quiet
= false;
123 char **argp
, *arg
, *p
;
125 openconsole(&dev_null_r
, &dev_stdcon_w
);
130 while ((arg
= *argp
) && arg
[0] == '-') {
131 if (!strcmp("-dhcpinfo", arg
)) {
134 fprintf(stderr
, "%s: unknown option: %s\n", progname
, arg
);
141 fprintf(stderr
, "%s: missing kernel name\n", progname
);
147 boot_image
= malloc(strlen(kernel_name
) + 12);
150 strcpy(boot_image
, "BOOT_IMAGE=");
151 strcpy(boot_image
+ 11, kernel_name
);
152 /* argp now points to the kernel name, and the command line follows.
153 Overwrite the kernel name with the BOOT_IMAGE= argument, and thus
154 we have the final argument. */
157 if (find_boolean(argp
, "quiet"))
161 printf("Loading %s... ", kernel_name
);
162 if (loadfile(kernel_name
, &kernel_data
, &kernel_len
)) {
164 printf("Loading %s ", kernel_name
);
171 cmdline
= make_cmdline(argp
);
175 /* Initialize the initramfs chain */
176 initramfs
= initramfs_init();
180 if ((arg
= find_argument(argp
, "initrd="))) {
182 p
= strchr(arg
, ',');
187 printf("Loading %s... ", arg
);
188 if (initramfs_load_archive(initramfs
, arg
)) {
190 printf("Loading %s ", kernel_name
);
202 /* Append the DHCP info */
204 !pxe_get_cached_info(PXENV_PACKET_TYPE_DHCP_ACK
, &dhcpdata
, &dhcplen
)) {
205 if (initramfs_add_file(initramfs
, dhcpdata
, dhcplen
, dhcplen
,
206 "/dhcpinfo.dat", 0, 0755))
210 /* This should not return... */
211 syslinux_boot_linux(kernel_data
, kernel_len
, initramfs
, cmdline
);
214 fprintf(stderr
, "Kernel load failure (insufficient memory?)\n");