2 * \file bootstrap/server/src/patch.c
3 * \brief Patching of boot modules
6 * \author Frank Mehnert <fm3@os.inf.tu-dresden.de> */
9 * (c) 2005-2009 Author(s)
10 * economic rights: Technische Universität Dresden (Germany)
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.
22 #include <l4/sys/consts.h>
23 #include <l4/util/mb_info.h>
27 #include "ARCH-x86/macros.h"
31 #include "ARCH-arm/macros.h"
35 #include "ARCH-amd64/macros.h"
39 #include "ARCH-ppc32/macros.h"
43 #include "ARCH-sparc/macros.h"
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,
57 const char *c = 0, *ce = 0;
60 for (i=0; i<mbi->mods_count; i++)
64 mod = (L4_MB_MOD_PTR(mbi->mods_addr)) + i;
65 m = c = L4_CONST_CHAR_PTR(mod->cmdline);
71 if (!(n = strchr(m, name[0])) || n+name_len>ce)
73 if (!memcmp(name, n, name_len))
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)
91 patch_module(const char **str, l4util_mb_info_t *mbi)
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;
101 /* nam_beg ... nam_end */
103 nam_end = strchr(nam_beg, ',');
104 if (!nam_end || strpbrk(nam_beg, "\011 =*")-1 < nam_end)
105 panic("-patch: bad module name");
107 mod = search_module(nam_beg, nam_end-nam_beg, mbi, &cmdline);
109 panic("-patch: cannot find module \"%.*s\"",
110 (int)(nam_end-nam_beg), nam_beg);
112 mod_beg = L4_CHAR_PTR(mod->mod_start);
113 mod_end = L4_CHAR_PTR(mod->mod_end);
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;
120 printf(" Patching module \"%s\"\n", cmdline);
122 for (var_beg=nam_end; *var_beg==','; var_beg=*str)
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;
131 /* val_beg ... val_end, consider quotes */
132 val_beg = val_end = var_end+1;
133 if (*val_end == '"' || *val_end == '\'')
138 while (*val_end && ((!quote && !isspace(*val_end) && *val_end!=',') ||
139 (quote && *val_end!=quote)))
145 val_size = val_end-val_beg;
147 /* replace all occurences of variable with value */
148 for (mod_ptr=mod_beg;;)
150 if (!(mod_ptr = (char *)memmem(mod_ptr, mod_end - mod_ptr,
151 var_beg, var_end - var_beg)))
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);
161 mod_end += val_size - var_size;
165 mod->mod_end = (l4_addr_t)mod_end;
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.
174 * Get a pointer to new argument and return the size.
177 get_arg_module(l4util_mb_info_t *mbi, const char *name, unsigned *size)
179 char *val_beg = NULL, *val_end;
180 char *s = (char *)get_cmdline(mbi);
185 while (!val_beg && (s = strstr(s, " -arg=")))
190 name_end = strchr(s, ',');
192 panic("comma missing after modname in -arg=");
197 panic("Invalid '-arg=modname,text' parameter");
199 // we do a fuzzy name-match here
201 val_beg = name_end+1;
208 unsigned char quote = 0;
209 if (*val_beg == '"' || *val_beg == '\'')
213 while (*val_end && ((!quote && !isspace(*val_end)) || *val_end!=quote))
216 *size = val_end - val_beg;