2 * Copyright (C) 2001-2003 Hewlett-Packard Co.
3 * Contributed by Stephane Eranian <eranian@hpl.hp.com>
4 * Copyright (C) 2006-2009 Intel Corporation
5 * Contributed by Fenghua Yu <fenghua.yu@intel.com>
6 * Contributed by Bibo Mao <bibo.mao@intel.com>
7 * Contributed by Chandramouli Narayanan <mouli@linux.intel.com>
9 * This file is part of the ELILO, the EFI Linux boot loader.
11 * ELILO is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
16 * ELILO is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with ELILO; see the file COPYING. If not, write to the Free
23 * Software Foundation, 59 Temple Place - Suite 330, Boston, MA
26 * Please check out the elilo.txt for complete documentation on how
27 * to use this program.
32 #include "glue_netfs.h"
40 * disable this if you only want the default config file (elilo.conf)
41 * and not the ip-address based first file attempt
44 static INTN glue(fileops_t *this, VOID *intf);
46 /* object exported to fileops */
47 fileops_fs_t netfs_glue = { NETFS_PROTOCOL , glue, netfs_install, netfs_uninstall};
50 #define NETFS_DEFAULT_KERNEL L"vmlinux"
51 #define NETFS_DEFAULT_CONFIG L"elilo.conf"
52 #define NETFS_DEFAULT_SERVER_TYPE EFI_PXE_BASE_CODE_BOOT_TYPE_REDHAT_BOOT
55 static CHAR16 netfs_default_path[FILENAME_MAXLEN];
59 * Pxe Discovery protocol layers
60 * Layer 0 is used to download the boot loader
62 #define NETFS_CONFIG_LAYER 1
63 #define NETFS_KERNEL_LAYER 2
65 static CHAR16 *hexa=L"0123456789ABCDEF";
68 convert_mac2hex(UINT8 *hw_addr,INTN l, CHAR16 *str)
72 for (i=0 ; i < l; i++) {
73 str[3*i] = hexa[(hw_addr[i] & 0xf0)>>4];
74 str[3*i+1] = hexa[hw_addr[i] & 0x0f];
81 convert_ip2hex(UINT8 *ip, INTN l, CHAR16 *str)
85 for(i=0; i < l; i++) {
86 str[2*i] = hexa[(ip[i] & 0xf0)>>4];
87 str[2*i+1] = hexa[ip[i] & 0x0f];
92 convert_ip2decstr(UINT8 *ip, INTN l, CHAR16 *str)
97 for(i=0, j=0; i < l; i++) {
105 if (v || ip[i] >= 100) {
111 if (i < l-1) str[j++] = L'.';
117 netfs_set_default_path(netfs_interface_t *netfs, netfs_info_t *info)
121 StrnCpy(netfs_default_path, info->bootfile, FILENAME_MAXLEN);
123 len = StrLen(netfs_default_path) - 1;
126 if (netfs_default_path[len] == CHAR_SLASH || netfs_default_path[len] == CHAR_BACKSLASH) break;
129 netfs_default_path[len+1] = CHAR_NULL;
131 DBG_PRT((L"netfs_default_path=%s\n", netfs_default_path));
137 netfs_setdefaults(VOID *intf, config_file_t *config, CHAR16 *kname, UINTN maxlen, CHAR16 *devpath)
139 netfs_interface_t *netfs = (netfs_interface_t *)intf;
144 CHAR16 ip_var[64], str[64];
147 if (config == NULL || kname == NULL || maxlen < 1) return EFI_INVALID_PARAMETER;
149 netfs->netfs_getinfo(netfs, &info);
151 m = info.using_ipv6 ? 16 : 4;
152 ipaddr = info.using_ipv6 ? info.cln_ipaddr.v6.Addr: info.cln_ipaddr.v4.Addr;
154 convert_ip2decstr(ipaddr, m, ip_var);
155 set_var(VAR_NETFS_IPADDR, ip_var);
157 ip = info.using_ipv6 ? info.netmask.v6.Addr: info.netmask.v4.Addr;
158 convert_ip2decstr(ip, m, str);
159 set_var(VAR_NETFS_NETMASK, str);
161 ip = info.using_ipv6 ? info.gw_ipaddr.v6.Addr: info.gw_ipaddr.v4.Addr;
162 convert_ip2decstr(ip, m, str);
163 set_var(VAR_NETFS_GATEWAY, str);
165 set_var(VAR_NETFS_HOSTNAME, info.hostname);
166 set_var(VAR_NETFS_DOMAINAME, info.domainame);
168 if (info.using_pxe) {
169 DBG_PRT((L"netfs_setdefaults: using_pxe"));
171 status = netfs->netfs_query_layer(netfs, 0, NETFS_CONFIG_LAYER, maxlen, config[0].fname);
172 if (EFI_ERROR(status)) {
173 StrnCpy(config[0].fname, NETFS_DEFAULT_CONFIG, maxlen-1);
174 config[0].fname[maxlen-1] = CHAR_NULL;
177 status = netfs->netfs_query_layer(netfs, 0, NETFS_KERNEL_LAYER, maxlen, kname);
178 if (EFI_ERROR(status)) {
179 StrnCpy(kname, NETFS_DEFAULT_KERNEL, maxlen-1);
180 kname[maxlen-1] = CHAR_NULL;
183 #ifdef ENABLE_MACHINE_SPECIFIC_NETCONFIG
185 # if defined(CONFIG_ia64)
186 # define CONFIG_ARCH_EXTENSION L"-ia64.conf\0"
187 # define EXTENSION_LENGTH 11
188 # elif defined (CONFIG_ia32)
189 # define CONFIG_ARCH_EXTENSION L"-ia32.conf\0"
190 # define EXTENSION_LENGTH 11
191 # elif defined (CONFIG_x86_64)
192 # define CONFIG_ARCH_EXTENSION L"-x86_64.conf\0"
193 # define EXTENSION_LENGTH 13
195 # error "You need to specfy your default arch config file"
198 # define CONFIG_EXTENSION L".conf\0"
200 DBG_PRT((L"netfs_setdefaults: machine specific (!using_pxe)"));
202 * will try machine/subnet specific files first.
203 * the filenames are constructed based on the IP(v4) address
205 convert_ip2hex(ipaddr, m, str);
206 StrnCpy(config[0].fname, str, maxlen-1);
207 StrnCpy(config[0].fname+8, CONFIG_EXTENSION, 6);
209 StrnCpy(config[1].fname, str, maxlen-1);
210 StrnCpy(config[1].fname+6, CONFIG_ARCH_EXTENSION, EXTENSION_LENGTH);
212 StrnCpy(config[2].fname, str, maxlen-1);
213 StrnCpy(config[2].fname+6, CONFIG_EXTENSION, 6);
215 StrnCpy(config[3].fname, str, maxlen-1);
216 StrnCpy(config[3].fname+4, CONFIG_ARCH_EXTENSION, EXTENSION_LENGTH);
218 StrnCpy(config[4].fname, str, maxlen-1);
219 StrnCpy(config[4].fname+4, CONFIG_EXTENSION, 6);
221 StrnCpy(config[5].fname, str, maxlen-1);
222 StrnCpy(config[5].fname+2, CONFIG_ARCH_EXTENSION, EXTENSION_LENGTH);
224 StrnCpy(config[6].fname, str, maxlen-1);
225 StrnCpy(config[6].fname+2, CONFIG_EXTENSION, 6);
227 /* use the MAC address as a possible file name as well */
228 convert_mac2hex(info.hw_addr,6,str);
229 StrnCpy(config[7].fname, str, maxlen-1);
230 StrnCpy(config[7].fname+17, CONFIG_EXTENSION, 6);
233 StrnCpy(config[0].fname, NETFS_DEFAULT_CONFIG, maxlen-1);
234 config[0].fname[maxlen-1] = CHAR_NULL;
236 StrnCpy(kname, NETFS_DEFAULT_KERNEL, maxlen-1);
237 kname[maxlen-1] = CHAR_NULL;
240 * extract bootloader path prefix to be used for
241 * the config file (and possibly the other files we
244 netfs_set_default_path(netfs, &info);
250 netfs_getdefault_path(CHAR16 *path, UINTN maxlen)
252 if (maxlen <= StrLen(netfs_default_path)) return EFI_BUFFER_TOO_SMALL;
254 StrCpy(path, netfs_default_path);
260 glue_open(VOID *intf, CHAR16 *name, fops_fd_t *fd)
262 netfs_interface_t *netfs = (netfs_interface_t *)intf;
263 CHAR16 fullname[FILENAME_MAXLEN];
265 if (name[0] != CHAR_SLASH && name[0] != CHAR_BACKSLASH && netfs_default_path[0] != CHAR_NULL) {
266 if (StrLen(netfs_default_path) + StrLen(name) + 1 >= FILENAME_MAXLEN)
267 return EFI_INVALID_PARAMETER;
269 StrCpy(fullname, netfs_default_path);
270 StrCat(fullname, name);
273 return netfs->netfs_open(intf, name, fd);
277 glue(fileops_t *fp, VOID *intf)
279 netfs_interface_t *netfs = (netfs_interface_t *)intf;
281 /* record underlying interface */
284 fp->open = glue_open;
285 fp->read = (fops_read_t)netfs->netfs_read;
286 fp->close = (fops_close_t)netfs->netfs_close;
287 fp->infosize = (fops_infosize_t)netfs->netfs_infosize;
288 fp->seek = (fops_seek_t)netfs->netfs_seek;
289 fp->setdefaults = (fops_setdefaults_t)netfs_setdefaults;
290 fp->getdefault_path = (fops_getdefault_path_t)netfs_getdefault_path;
293 /* fill out the name of the underlying file system */
294 netfs->netfs_name(netfs, fp->name, FILEOPS_NAME_MAXLEN);