orphan
[debian/elilo] / glue_localfs.c
1 /*
2  *  Copyright (C) 2001-2003 Hewlett-Packard Co.
3  *      Contributed by Stephane Eranian <eranian@hpl.hp.com>
4  *
5  * This file is part of the ELILO, the EFI Linux boot loader.
6  *
7  *  ELILO is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2, or (at your option)
10  *  any later version.
11  *
12  *  ELILO is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with ELILO; see the file COPYING.  If not, write to the Free
19  *  Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20  *  02111-1307, USA.
21  *
22  * Please check out the elilo.txt for complete documentation on how
23  * to use this program.
24  */
25 #include <efi.h>
26 #include <efilib.h>
27
28 #include "fs/localfs.h"
29 #include "glue_localfs.h"
30 #include "strops.h"
31 #include "elilo.h"
32
33 static INTN glue(fileops_t *this, VOID *intf);
34
35 /* object exported to fileops */
36
37 fileops_fs_t localfs_glue = { LOCALFS_PROTOCOL, glue, localfs_install, localfs_uninstall};
38
39
40 static CHAR16 localfs_default_path[FILENAME_MAXLEN];
41
42 /*
43  * remove /.\ pattern from path name:
44  *
45  * Example 1:  I am in fs0:\efi\debian, which contains elilo.efi, and I
46  * have typed 'elilo' at the efishell prompt.  set_default_path() gets
47  * called with string "\EFI\debian/.\elilo.efi". The final path name
48  * must then be set to "\EFI\debian\".
49  * 
50  * Example 2:  I am in fs0:\ and type 'efi\debian\elilo' at the shell
51  * prompt.  set_default_path() is called with "\/.\efi\debian\elilo.efi",
52  * the path must then be set to "\efi\debian\".
53  *
54  * Example 3:  I am in fs0:\efi and type '\efi\debian\elilo'.
55  * set_default_path() is called with "\efi\debian\elilo.efi", the
56  * path is "\efi\debian".
57  */
58 static VOID
59 set_default_path(CHAR16 *sptr)
60 {
61 #define is_sep(h)       (h == CHAR_SLASH || h == CHAR_BACKSLASH)
62         CHAR16 *dptr, *last_sep = NULL;
63         UINTN len = FILENAME_MAXLEN - 1;
64         UINTN last_was_sep = 0;
65         CHAR16 c;
66
67         dptr = localfs_default_path;
68
69         while (len-- && *sptr) {
70                 c = sptr[0];
71
72                 if (is_sep(c)) {
73                         if (last_was_sep) {
74                                 sptr++;
75                                 continue;
76                         }
77                         c = CHAR_BACKSLASH;
78                         last_was_sep = 1;
79                         last_sep = dptr;
80                 } else {
81                         last_was_sep = 0;
82                 }
83                 *dptr++ = c;
84                 sptr++;
85         }
86         if (last_sep)
87                 *++last_sep = CHAR_NULL;
88         else
89                 *dptr = CHAR_NULL;
90
91         DBG_PRT((L"localfs_default_path=%s\n", localfs_default_path));
92 }
93
94
95 /*
96  * The following glue functions are the only ones which need
97  * to know about the way the underlying interface is working
98  */
99 #define LOCALFS_DEFAULT_KERNEL  L"vmlinux"
100 #define LOCALFS_DEFAULT_CONFIG  L"elilo.conf"
101 static EFI_STATUS
102 localfs_setdefaults(VOID *this, config_file_t *config, CHAR16 *kname, UINTN maxlen, CHAR16 *devpath)
103 {
104         StrnCpy(kname, LOCALFS_DEFAULT_KERNEL, maxlen-1);
105         kname[maxlen-1] = CHAR_NULL;
106
107         StrnCpy(config[0].fname, LOCALFS_DEFAULT_CONFIG, maxlen-1);
108         config[0].fname[maxlen-1] = CHAR_NULL;
109
110         set_default_path(devpath);
111
112         return EFI_SUCCESS;
113 }
114
115 static EFI_STATUS
116 localfs_getdefault_path(CHAR16 *path, UINTN maxlen)
117 {
118         if (maxlen <= StrLen(localfs_default_path)) return EFI_BUFFER_TOO_SMALL;
119
120         StrCpy(path, localfs_default_path);
121         return EFI_SUCCESS;
122 }
123
124 /*
125  * If the supplied path is a relative path, then prepend the path to
126  * the elilo.efi executable.  This ensures that elilo will look in
127  * its own directory for its config file, kernel images, etc, rather
128  * than the root directory of the disk.  Also * convert forward slashes
129  * into backward slashes.
130  */
131 static EFI_STATUS 
132 glue_open(VOID *intf, CHAR16 *name, fops_fd_t *fd)
133 {
134         CHAR16 *p;
135         localfs_interface_t *localfs = (localfs_interface_t *)intf;
136         CHAR16 fullname[FILENAME_MAXLEN];
137
138         /*
139          * XXX: modification to passed argument (name)
140          */
141         for (p= name; *p != CHAR_NULL; p++) {
142                 if (*p == CHAR_SLASH) *p = CHAR_BACKSLASH;
143         }
144         if (name[0] != CHAR_BACKSLASH && localfs_default_path[0] != CHAR_NULL) {
145                 if (StrLen(localfs_default_path) + StrLen(name) + 1 >= FILENAME_MAXLEN)
146                         return EFI_INVALID_PARAMETER;
147
148                 StrCpy(fullname, localfs_default_path);
149                 StrCat(fullname, name);
150                 name = fullname;
151         }
152         return localfs->localfs_open(intf, name, fd);
153 }
154
155 static INTN
156 glue(fileops_t *fp, VOID *intf)
157 {
158         localfs_interface_t *localfs = (localfs_interface_t *)intf;
159
160         fp->open            = glue_open;
161         fp->read            = (fops_read_t)localfs->localfs_read;
162         fp->close           = (fops_close_t)localfs->localfs_close;
163         fp->infosize        = (fops_infosize_t)localfs->localfs_infosize;
164         fp->seek            = (fops_seek_t)localfs->localfs_seek;
165         fp->setdefaults     = (fops_setdefaults_t)localfs_setdefaults;
166         fp->getdefault_path = (fops_getdefault_path_t)localfs_getdefault_path;
167         fp->intf            = intf;
168
169         /* fill out the name of the underlying file system */
170         localfs->localfs_name(localfs, fp->name, FILEOPS_NAME_MAXLEN);
171
172         return 0;
173 }