]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/bootstrap/server/src/patch.cc
update
[l4.git] / l4 / pkg / bootstrap / server / src / patch.cc
1 /**
2  * \file        bootstrap/server/src/patch.c
3  * \brief       Patching of boot modules
4  * 
5  * \date        09/2005
6  * \author      Frank Mehnert <fm3@os.inf.tu-dresden.de> */
7
8 /*
9  * (c) 2005-2009 Author(s)
10  *     economic rights: Technische Universität Dresden (Germany)
11  *
12  * This file is part of TUD:OS and distributed under the terms of the
13  * GNU General Public License 2.
14  * Please see the COPYING-GPL-2 file for details.
15  */
16
17 #include <ctype.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21
22 #include <l4/sys/consts.h>
23 #include <l4/util/mb_info.h>
24 #include "panic.h"
25
26 #ifdef ARCH_x86
27 #include "ARCH-x86/macros.h"
28 #endif
29
30 #ifdef ARCH_arm
31 #include "ARCH-arm/macros.h"
32 #endif
33
34 #ifdef ARCH_amd64
35 #include "ARCH-amd64/macros.h"
36 #endif
37
38 #ifdef ARCH_ppc32
39 #include "ARCH-ppc32/macros.h"
40 #endif
41
42 #ifdef ARCH_sparc
43 #include "ARCH-sparc/macros.h"
44 #endif
45
46 #include "types.h"
47 #include "patch.h"
48 #include "startup.h"
49
50
51 /* search module in module list */
52 static l4util_mb_mod_t*
53 search_module(const char *name, size_t name_len, l4util_mb_info_t *mbi,
54               const char **cmdline)
55 {
56   unsigned i;
57   const char *c = 0, *ce = 0;
58   l4util_mb_mod_t *mod;
59
60   for (i=0; i<mbi->mods_count; i++)
61     {
62       const char *m, *n;
63
64       mod = (L4_MB_MOD_PTR(mbi->mods_addr)) + i;
65       m = c = L4_CONST_CHAR_PTR(mod->cmdline);
66       ce = strchr(c, ' ');
67       if (!ce)
68         ce = c+strlen(c);
69       for (;;)
70         {
71           if (!(n = strchr(m, name[0])) || n+name_len>ce)
72             break;
73           if (!memcmp(name, n, name_len))
74             {
75               *cmdline = c;
76               return mod;
77             }
78           m = n+1;
79         }
80     }
81
82   return NULL;
83 }
84
85 /**
86  * Handle -patch=<module_name>,<variable>=blah parameter. Overwrite a specific
87  * module from command line. This allows to change the boot configuration (e.g.
88  * changing parameters of a loader script)
89  */
90 void
91 patch_module(const char **str, l4util_mb_info_t *mbi)
92 {
93   const char *nam_beg, *nam_end;
94   const char *var_beg, *var_end;
95   const char *val_beg, *val_end;
96   char *mod_beg, *mod_end, *mod_ptr, quote = 0;
97   l4_size_t var_size, val_size, max_patch_size;
98   const char *cmdline = 0;
99   l4util_mb_mod_t *mod;
100
101   /* nam_beg ... nam_end */
102   nam_beg = *str+8;
103   nam_end = strchr(nam_beg, ',');
104   if (!nam_end || strpbrk(nam_beg, "\011 =*")-1 < nam_end)
105     panic("-patch: bad module name");
106
107   mod = search_module(nam_beg, nam_end-nam_beg, mbi, &cmdline);
108   if (!mod)
109     panic("-patch: cannot find module \"%.*s\"",
110           (int)(nam_end-nam_beg), nam_beg);
111
112   mod_beg = L4_CHAR_PTR(mod->mod_start);
113   mod_end = L4_CHAR_PTR(mod->mod_end);
114
115   /* How much bytes the module can be enlarged to. The module cannot
116    * be extended beyond page boundaries because the next module starts
117    * there and we don't want to move the following modules. */
118   max_patch_size = l4_round_page((l4_addr_t)mod_end) - (l4_addr_t)mod_end - 1;
119
120   printf("  Patching module \"%s\"\n", cmdline);
121
122   for (var_beg=nam_end; *var_beg==','; var_beg=*str)
123     {
124       var_beg++;
125       /* var_beg ... var_end */
126       var_end = strchr(var_beg, '=');
127       if (!var_end || strpbrk(var_beg, "\011 ,*")-1 < nam_end)
128         panic("-patch: bad variable name");
129       var_size = var_end-var_beg;
130
131       /* val_beg ... val_end, consider quotes */
132       val_beg = val_end = var_end+1;
133       if (*val_end == '"' || *val_end == '\'')
134         {
135           val_beg++;
136           quote = *val_end++;
137         }
138       while (*val_end && ((!quote && !isspace(*val_end) && *val_end!=',') ||
139                           (quote && *val_end!=quote)))
140         val_end++;
141       *str = val_end;
142       if (quote)
143         (*str)++;
144       quote = 0;
145       val_size = val_end-val_beg;
146
147       /* replace all occurences of variable with value */
148       for (mod_ptr=mod_beg;;)
149         {
150           if (!(mod_ptr = (char *)memmem(mod_ptr, mod_end - mod_ptr,
151                                          var_beg, var_end - var_beg)))
152             break;
153           if (var_size < val_size && max_patch_size < val_size-var_size)
154             panic("-patch: not enough space in module");
155           max_patch_size += var_size - val_size;
156           memmove(mod_ptr+val_size, mod_ptr+var_size, mod_end-mod_ptr-var_size);
157           if (val_size < var_size)
158             memset(mod_end-var_size+val_size, 0, var_size-val_size);
159           memcpy(mod_ptr, val_beg, val_size);
160           mod_ptr += val_size;
161           mod_end += val_size - var_size;
162         }
163     }
164
165   mod->mod_end = (l4_addr_t)mod_end;
166 }
167
168
169 /**
170  * Handle -arg=<module_name>,blah parameter. Replace old command line
171  * parameters of <module_name> by blah. Useful for changing the boot
172  * configuration of a bootstrap image.
173  *
174  * Get a pointer to new argument and return the size.
175  */
176 char *
177 get_arg_module(l4util_mb_info_t *mbi, const char *name, unsigned *size)
178 {
179   char *val_beg = NULL, *val_end;
180   char *s = (char *)get_cmdline(mbi);
181
182   if (!s)
183     return 0;
184
185   while (!val_beg && (s = strstr(s, " -arg=")))
186     {
187       char *a, *name_end;
188
189       s += 6;
190       name_end = strchr(s, ',');
191       if (!name_end)
192         panic("comma missing after modname in -arg=");
193       *name_end = 0;
194
195       for (a = s; *a; a++)
196         if (isspace(*a))
197           panic("Invalid '-arg=modname,text' parameter");
198
199       // we do a fuzzy name-match here
200       if (strstr(name, s))
201         val_beg = name_end+1;
202       *name_end = ',';
203     }
204   if (!val_beg)
205     return 0;
206
207   // consider quotes
208   unsigned char quote = 0;
209   if (*val_beg == '"' || *val_beg == '\'')
210     quote = *val_beg++;
211   val_end = val_beg;
212
213   while (*val_end && ((!quote && !isspace(*val_end)) || *val_end!=quote))
214     val_end++;
215
216   *size = val_end - val_beg;
217   return val_beg;
218 }