]>
Commit | Line | Data |
---|---|---|
cd46aa6c VS |
1 | /* |
2 | * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2013 Free Software Foundation, Inc. | |
3 | * | |
4 | * GRUB is free software: you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation, either version 3 of the License, or | |
7 | * (at your option) any later version. | |
8 | * | |
9 | * GRUB is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with GRUB. If not, see <http://www.gnu.org/licenses/>. | |
16 | */ | |
17 | ||
18 | #include <config.h> | |
19 | ||
20 | #include <grub/util/install.h> | |
21 | #include <grub/emu/config.h> | |
22 | #include <grub/util/misc.h> | |
23 | ||
24 | #include <argp.h> | |
25 | #include <string.h> | |
26 | #include <errno.h> | |
27 | ||
28 | static char *rootdir = NULL, *subdir = NULL; | |
29 | static char *debug_image = NULL; | |
30 | ||
31 | enum | |
32 | { | |
33 | OPTION_NET_DIRECTORY = 0x301, | |
34 | OPTION_SUBDIR, | |
35 | OPTION_DEBUG, | |
36 | OPTION_DEBUG_IMAGE | |
37 | }; | |
38 | ||
39 | static struct argp_option options[] = { | |
40 | GRUB_INSTALL_OPTIONS, | |
41 | {"net-directory", OPTION_NET_DIRECTORY, N_("DIR"), | |
42 | 0, N_("root directory of TFTP server"), 2}, | |
43 | {"subdir", OPTION_SUBDIR, N_("DIR"), | |
44 | 0, N_("relative subdirectory on network server"), 2}, | |
45 | {"debug", OPTION_DEBUG, 0, OPTION_HIDDEN, 0, 2}, | |
46 | {"debug-image", OPTION_DEBUG_IMAGE, "DEBUG", OPTION_HIDDEN, 0, 2}, | |
47 | {0, 0, 0, 0, 0, 0} | |
48 | }; | |
49 | ||
50 | static error_t | |
51 | argp_parser (int key, char *arg, struct argp_state *state) | |
52 | { | |
53 | if (grub_install_parse (key, arg)) | |
54 | return 0; | |
55 | switch (key) | |
56 | { | |
57 | case OPTION_NET_DIRECTORY: | |
58 | free (rootdir); | |
59 | rootdir = xstrdup (arg); | |
60 | return 0; | |
61 | case OPTION_SUBDIR: | |
62 | free (subdir); | |
63 | subdir = xstrdup (arg); | |
64 | return 0; | |
65 | /* This is an undocumented feature... */ | |
66 | case OPTION_DEBUG: | |
67 | verbosity++; | |
68 | return 0; | |
69 | case OPTION_DEBUG_IMAGE: | |
70 | free (debug_image); | |
71 | debug_image = xstrdup (arg); | |
72 | return 0; | |
73 | ||
74 | case ARGP_KEY_ARG: | |
75 | default: | |
76 | return ARGP_ERR_UNKNOWN; | |
77 | } | |
78 | } | |
79 | ||
80 | ||
81 | struct argp argp = { | |
82 | options, argp_parser, N_("[OPTION]"), | |
83 | "\v"N_("copies GRUB images into net_directory/subdir/target_cpu-platform."), | |
84 | NULL, grub_install_help_filter, NULL | |
85 | }; | |
86 | ||
87 | static char *base; | |
88 | ||
89 | static const struct | |
90 | { | |
91 | const char *mkimage_target; | |
92 | const char *netmodule; | |
93 | const char *ext; | |
94 | } targets[GRUB_INSTALL_PLATFORM_MAX] = | |
95 | { | |
96 | [GRUB_INSTALL_PLATFORM_I386_PC] = { "i386-pc-pxe", "pxe", ".0" }, | |
97 | [GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275] = { "sparc64-ieee1275-aout", "ofnet", ".img" }, | |
98 | [GRUB_INSTALL_PLATFORM_I386_IEEE1275] = { "i386-ieee1275", "ofnet", ".elf" }, | |
99 | [GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275] = { "powerpc-ieee1275", "ofnet", ".elf" }, | |
100 | [GRUB_INSTALL_PLATFORM_I386_EFI] = { "i386-efi", "efinet", ".efi" }, | |
101 | [GRUB_INSTALL_PLATFORM_X86_64_EFI] = { "x86_64-efi", "efinet", ".efi" }, | |
102 | [GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64-efi", "efinet", ".efi" }, | |
103 | [GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm-efi", "efinet", ".efi" } | |
104 | }; | |
105 | ||
106 | static void | |
107 | process_input_dir (const char *input_dir, enum grub_install_plat platform) | |
108 | { | |
109 | char *platsub = grub_install_get_platform_name (platform); | |
110 | char *grubdir = grub_util_path_concat (3, rootdir, subdir, platsub); | |
111 | char *load_cfg = grub_util_path_concat (2, grubdir, "load.cfg"); | |
112 | char *prefix; | |
113 | char *output; | |
114 | char *grub_cfg; | |
115 | FILE *cfg; | |
116 | ||
117 | grub_install_copy_files (input_dir, base, platform); | |
118 | grub_util_unlink (load_cfg); | |
119 | ||
120 | if (debug_image) | |
121 | { | |
122 | FILE *f = grub_util_fopen (load_cfg, "wb"); | |
123 | if (!f) | |
124 | grub_util_error (_("cannot open `%s': %s"), load_cfg, | |
125 | strerror (errno)); | |
126 | fprintf (f, "set debug='%s'\n", debug_image); | |
127 | fclose (f); | |
128 | } | |
129 | else | |
130 | { | |
131 | free (load_cfg); | |
132 | load_cfg = 0; | |
133 | } | |
134 | ||
135 | prefix = xasprintf ("/%s", subdir); | |
136 | if (!targets[platform].mkimage_target) | |
137 | grub_util_error ("unsupported platform %s\n", platsub); | |
138 | ||
139 | grub_cfg = grub_util_path_concat (2, grubdir, "grub.cfg"); | |
140 | cfg = grub_util_fopen (grub_cfg, "wb"); | |
141 | if (!cfg) | |
142 | grub_util_error (_("cannot open `%s': %s"), grub_cfg, | |
143 | strerror (errno)); | |
144 | fprintf (cfg, "source %s/grub.cfg", subdir); | |
145 | fclose (cfg); | |
146 | ||
147 | grub_install_push_module (targets[platform].netmodule); | |
148 | ||
149 | output = grub_util_path_concat_ext (2, grubdir, "core", targets[platform].ext); | |
150 | grub_install_make_image_wrap (input_dir, prefix, output, | |
151 | 0, load_cfg, | |
f23bc651 | 152 | targets[platform].mkimage_target, 0); |
cd46aa6c VS |
153 | grub_install_pop_module (); |
154 | ||
155 | /* TRANSLATORS: First %s is replaced by platform name. Second one by filename. */ | |
156 | printf (_("Netboot directory for %s created. Configure your DHCP server to point to %s\n"), | |
157 | platsub, output); | |
158 | ||
159 | free (platsub); | |
160 | free (output); | |
161 | free (prefix); | |
162 | free (grub_cfg); | |
163 | free (grubdir); | |
164 | } | |
165 | ||
166 | ||
167 | int | |
168 | main (int argc, char *argv[]) | |
169 | { | |
bee1b5ce | 170 | const char *pkglibdir; |
cd46aa6c VS |
171 | |
172 | grub_util_host_init (&argc, &argv); | |
5c7206e4 | 173 | grub_util_disable_fd_syncs (); |
cd46aa6c | 174 | rootdir = xstrdup ("/srv/tftp"); |
bee1b5ce | 175 | pkglibdir = grub_util_get_pkglibdir (); |
cd46aa6c VS |
176 | |
177 | subdir = grub_util_path_concat (2, GRUB_BOOT_DIR_NAME, GRUB_DIR_NAME); | |
178 | ||
179 | argp_parse (&argp, argc, argv, 0, 0, 0); | |
180 | ||
181 | base = grub_util_path_concat (2, rootdir, subdir); | |
182 | /* Create the GRUB directory if it is not present. */ | |
183 | ||
184 | grub_install_mkdir_p (base); | |
185 | ||
186 | grub_install_push_module ("tftp"); | |
187 | ||
188 | if (!grub_install_source_directory) | |
189 | { | |
190 | enum grub_install_plat plat; | |
191 | ||
192 | for (plat = 0; plat < GRUB_INSTALL_PLATFORM_MAX; plat++) | |
193 | if (targets[plat].mkimage_target) | |
194 | { | |
bee1b5ce | 195 | char *platdir = grub_util_path_concat (2, pkglibdir, |
cd46aa6c VS |
196 | grub_install_get_platform_name (plat)); |
197 | ||
bee1b5ce VS |
198 | grub_util_info ("Looking for `%s'", platdir); |
199 | ||
cd46aa6c VS |
200 | if (!grub_util_is_directory (platdir)) |
201 | { | |
202 | free (platdir); | |
203 | continue; | |
204 | } | |
205 | process_input_dir (platdir, plat); | |
206 | } | |
207 | } | |
208 | else | |
209 | { | |
210 | enum grub_install_plat plat; | |
211 | plat = grub_install_get_target (grub_install_source_directory); | |
212 | process_input_dir (grub_install_source_directory, plat); | |
213 | } | |
214 | return 0; | |
215 | } |