fix lintian complaints
[debian/elilo] / glue_netfs.c
1 /*
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>
8  *
9  * This file is part of the ELILO, the EFI Linux boot loader.
10  *
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)
14  *  any later version.
15  *
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.
20  *
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
24  *  02111-1307, USA.
25  *
26  * Please check out the elilo.txt for complete documentation on how
27  * to use this program.
28  */
29 #include <efi.h>
30 #include <efilib.h>
31
32 #include "glue_netfs.h"
33 #include "fs/netfs.h"
34 #include "strops.h"
35
36 #include "elilo.h"
37 #include "vars.h"
38
39 /*
40  * disable this if you only want the default config file (elilo.conf)
41  * and not the ip-address based first file attempt
42  */
43
44 static INTN glue(fileops_t *this, VOID *intf);
45
46 /* object exported to fileops */
47 fileops_fs_t netfs_glue = { NETFS_PROTOCOL  , glue, netfs_install, netfs_uninstall};
48         
49
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
53
54
55 static CHAR16 netfs_default_path[FILENAME_MAXLEN];
56
57
58 /*
59  * Pxe Discovery protocol layers
60  * Layer 0 is used to download the boot loader
61  */
62 #define NETFS_CONFIG_LAYER      1
63 #define NETFS_KERNEL_LAYER      2
64
65 static CHAR16 *hexa=L"0123456789ABCDEF";
66
67 static VOID
68 convert_ip2hex(UINT8 *ip, INTN l, CHAR16 *str)
69 {
70         UINTN i;
71
72         for(i=0; i < l; i++) {
73                 str[2*i]   = hexa[(ip[i] & 0xf0)>>4];
74                 str[2*i+1] = hexa[ip[i] & 0x0f];
75         }
76 }
77
78 static VOID
79 convert_ip2decstr(UINT8 *ip, INTN l, CHAR16 *str)
80 {
81         UINTN i, j;
82         UINTN v, val;
83
84         for(i=0, j=0; i < l; i++) {
85                 val = ip[i];
86                 v = val / 100;
87                 if (v) {
88                         str[j++] = L'0'+v;
89                 }
90                 val = val % 100;
91                 v = val / 10;
92                 if (v || ip[i] >= 100) {
93                         str[j++] = L'0'+v;
94                 }
95
96                 v = val % 10;
97                 str[j++] = L'0'+v;
98                 if (i < l-1) str[j++] = L'.';
99         }
100         str[j] = CHAR_NULL;
101 }
102
103 static int
104 netfs_set_default_path(netfs_interface_t *netfs, netfs_info_t *info)
105 {
106         INTN len;
107
108         StrnCpy(netfs_default_path, info->bootfile, FILENAME_MAXLEN);
109
110         len = StrLen(netfs_default_path) - 1;
111
112         while (len >= 0) {
113                 if (netfs_default_path[len] == CHAR_SLASH || netfs_default_path[len] == CHAR_BACKSLASH) break;
114                 len--;
115         }
116         netfs_default_path[len+1] = CHAR_NULL;
117  
118         DBG_PRT((L"netfs_default_path=%s\n", netfs_default_path));
119
120         return EFI_SUCCESS;
121 }
122
123 static EFI_STATUS
124 netfs_setdefaults(VOID *intf, config_file_t *config, CHAR16 *kname, UINTN maxlen, CHAR16 *devpath)
125 {
126         netfs_interface_t *netfs = (netfs_interface_t *)intf;
127         netfs_info_t info;
128         EFI_STATUS status;
129         UINT8 *ipaddr;
130         UINTN m;
131         CHAR16 ip_var[64], str[64];
132         UINT8 *ip;
133
134         if (config == NULL || kname == NULL || maxlen < 1) return EFI_INVALID_PARAMETER;
135
136         netfs->netfs_getinfo(netfs, &info);
137
138         m      = info.using_ipv6 ? 16 : 4;
139         ipaddr = info.using_ipv6 ? info.cln_ipaddr.v6.Addr: info.cln_ipaddr.v4.Addr;
140
141         convert_ip2decstr(ipaddr, m, ip_var);
142         set_var(VAR_NETFS_IPADDR, ip_var);
143
144         ip = info.using_ipv6 ? info.netmask.v6.Addr: info.netmask.v4.Addr;
145         convert_ip2decstr(ip, m, str);
146         set_var(VAR_NETFS_NETMASK, str);
147
148         ip = info.using_ipv6 ? info.gw_ipaddr.v6.Addr: info.gw_ipaddr.v4.Addr;
149         convert_ip2decstr(ip, m, str);
150         set_var(VAR_NETFS_GATEWAY, str);
151
152         set_var(VAR_NETFS_HOSTNAME, info.hostname);
153         set_var(VAR_NETFS_DOMAINAME, info.domainame);
154
155         if (info.using_pxe) {
156                 status = netfs->netfs_query_layer(netfs, 0, NETFS_CONFIG_LAYER, maxlen, config[0].fname);
157                 if (EFI_ERROR(status)) {
158                         StrnCpy(config[0].fname, NETFS_DEFAULT_CONFIG, maxlen-1);
159                         config[0].fname[maxlen-1] = CHAR_NULL;
160                 }
161
162                 status = netfs->netfs_query_layer(netfs, 0, NETFS_KERNEL_LAYER, maxlen, kname);
163                 if (EFI_ERROR(status)) {
164                         StrnCpy(kname, NETFS_DEFAULT_KERNEL, maxlen-1);
165                         kname[maxlen-1] = CHAR_NULL;
166                 }
167         } else {
168 #ifdef ENABLE_MACHINE_SPECIFIC_NETCONFIG
169
170 #  if defined(CONFIG_ia64)
171 #    define CONFIG_ARCH_EXTENSION L"-ia64.conf\0"
172 #    define EXTENSION_LENGTH 11
173 #  elif defined (CONFIG_ia32)
174 #    define CONFIG_ARCH_EXTENSION L"-ia32.conf\0"
175 #    define EXTENSION_LENGTH 11
176 #  elif defined (CONFIG_x86_64)
177 #    define CONFIG_ARCH_EXTENSION L"-x86_64.conf\0"
178 #    define EXTENSION_LENGTH 13
179 #  else
180 #    error "You need to specfy your default arch config file"
181 #  endif            
182
183 #  define CONFIG_EXTENSION L".conf\0"
184                 /*
185                  * will try machine/subnet specific files first.
186                  * the filenames are constructed based on the IP(v4) address
187                  */
188                 convert_ip2hex(ipaddr, m, str);
189                 StrnCpy(config[0].fname, str, maxlen-1);
190                 StrnCpy(config[0].fname+8, CONFIG_EXTENSION, 6);
191
192                 StrnCpy(config[1].fname, str, maxlen-1);
193                 StrnCpy(config[1].fname+6, CONFIG_ARCH_EXTENSION, EXTENSION_LENGTH);
194
195                 StrnCpy(config[2].fname, str, maxlen-1);
196                 StrnCpy(config[2].fname+6, CONFIG_EXTENSION, 6);
197
198                 StrnCpy(config[3].fname, str, maxlen-1);
199                 StrnCpy(config[3].fname+4, CONFIG_ARCH_EXTENSION, EXTENSION_LENGTH);
200
201                 StrnCpy(config[4].fname, str, maxlen-1);
202                 StrnCpy(config[4].fname+4, CONFIG_EXTENSION, 6);
203                 
204                 StrnCpy(config[5].fname, str, maxlen-1);
205                 StrnCpy(config[5].fname+2, CONFIG_ARCH_EXTENSION, EXTENSION_LENGTH);
206
207                 StrnCpy(config[6].fname, str, maxlen-1);
208                 StrnCpy(config[6].fname+2, CONFIG_EXTENSION, 6);
209 #else
210                 StrnCpy(config[0].fname, NETFS_DEFAULT_CONFIG, maxlen-1);
211                 config[0].fname[maxlen-1] = CHAR_NULL;
212 #endif
213                 StrnCpy(kname, NETFS_DEFAULT_KERNEL, maxlen-1);
214                 kname[maxlen-1] = CHAR_NULL;
215
216                 /*
217                  * extract bootloader path prefix to be used for 
218                  * the config file (and possibly the other files we 
219                  * need to download)
220                  */
221                 netfs_set_default_path(netfs, &info);
222         }
223         return EFI_SUCCESS;
224 }
225
226 static EFI_STATUS
227 netfs_getdefault_path(CHAR16 *path, UINTN maxlen)
228 {
229         if (maxlen <= StrLen(netfs_default_path)) return EFI_BUFFER_TOO_SMALL;
230
231         StrCpy(path, netfs_default_path);
232         return EFI_SUCCESS;
233 }
234
235
236 static EFI_STATUS 
237 glue_open(VOID *intf, CHAR16 *name, fops_fd_t *fd)
238 {
239         netfs_interface_t *netfs = (netfs_interface_t *)intf;
240         CHAR16 fullname[FILENAME_MAXLEN];
241
242         if (name[0] != CHAR_SLASH && name[0] != CHAR_BACKSLASH && netfs_default_path[0] != CHAR_NULL) {
243                 if (StrLen(netfs_default_path) + StrLen(name) + 1 >= FILENAME_MAXLEN)
244                         return EFI_INVALID_PARAMETER;
245
246                 StrCpy(fullname, netfs_default_path);
247                 StrCat(fullname, name);
248                 name = fullname;
249         }
250         return netfs->netfs_open(intf, name, fd);
251 }
252
253 static INTN
254 glue(fileops_t *fp, VOID *intf)
255 {
256         netfs_interface_t *netfs = (netfs_interface_t *)intf;
257
258         /* record underlying interface */
259         fp->intf        = intf;
260
261         fp->open            = glue_open;
262         fp->read            = (fops_read_t)netfs->netfs_read;
263         fp->close           = (fops_close_t)netfs->netfs_close;
264         fp->infosize        = (fops_infosize_t)netfs->netfs_infosize;
265         fp->seek            = (fops_seek_t)netfs->netfs_seek;
266         fp->setdefaults     = (fops_setdefaults_t)netfs_setdefaults;
267         fp->getdefault_path = (fops_getdefault_path_t)netfs_getdefault_path;
268         fp->intf            = intf;
269
270         /* fill out the name of the underlying file system */
271         netfs->netfs_name(netfs, fp->name, FILEOPS_NAME_MAXLEN);
272
273         return 0;
274 }