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>
31 /* search module in module list */
32 static l4util_mb_mod_t*
33 search_module(const char *name, size_t name_len, l4util_mb_info_t *mbi,
37 const char *c = 0, *ce = 0;
40 for (i=0; i<mbi->mods_count; i++)
44 mod = (L4_MB_MOD_PTR(mbi->mods_addr)) + i;
45 m = c = L4_CONST_CHAR_PTR(mod->cmdline);
51 if (!(n = strchr(m, name[0])) || n+name_len>ce)
53 if (!memcmp(name, n, name_len))
66 * Handle -patch=<module_name>,<variable>=blah parameter. Overwrite a specific
67 * module from command line. This allows to change the boot configuration (e.g.
68 * changing parameters of a loader script)
71 patch_module(const char **str, l4util_mb_info_t *mbi)
73 const char *nam_beg, *nam_end;
74 const char *var_beg, *var_end;
75 const char *val_beg, *val_end;
76 char *mod_beg, *mod_end, *mod_ptr, quote = 0;
77 l4_size_t var_size, val_size, max_patch_size;
78 const char *cmdline = 0;
81 /* nam_beg ... nam_end */
83 nam_end = strchr(nam_beg, ',');
84 if (!nam_end || strpbrk(nam_beg, "\011 =*")-1 < nam_end)
85 panic("-patch: bad module name");
87 mod = search_module(nam_beg, nam_end-nam_beg, mbi, &cmdline);
89 panic("-patch: cannot find module \"%.*s\"",
90 (int)(nam_end-nam_beg), nam_beg);
92 mod_beg = L4_CHAR_PTR(mod->mod_start);
93 mod_end = L4_CHAR_PTR(mod->mod_end);
95 /* How much bytes the module can be enlarged to. The module cannot
96 * be extended beyond page boundaries because the next module starts
97 * there and we don't want to move the following modules. */
98 max_patch_size = l4_round_page((l4_addr_t)mod_end) - (l4_addr_t)mod_end - 1;
100 printf(" Patching module \"%s\"\n", cmdline);
102 for (var_beg=nam_end; *var_beg==','; var_beg=*str)
105 /* var_beg ... var_end */
106 var_end = strchr(var_beg, '=');
107 if (!var_end || strpbrk(var_beg, "\011 ,*")-1 < nam_end)
108 panic("-patch: bad variable name");
109 var_size = var_end-var_beg;
111 /* val_beg ... val_end, consider quotes */
112 val_beg = val_end = var_end+1;
113 if (*val_end == '"' || *val_end == '\'')
118 while (*val_end && ((!quote && !isspace(*val_end) && *val_end!=',') ||
119 (quote && *val_end!=quote)))
125 val_size = val_end-val_beg;
127 /* replace all occurences of variable with value */
128 for (mod_ptr=mod_beg;;)
130 if (!(mod_ptr = (char *)memmem(mod_ptr, mod_end - mod_ptr,
131 var_beg, var_end - var_beg)))
133 if (var_size < val_size && max_patch_size < val_size-var_size)
134 panic("-patch: not enough space in module");
135 max_patch_size += var_size - val_size;
136 memmove(mod_ptr+val_size, mod_ptr+var_size, mod_end-mod_ptr-var_size);
137 if (val_size < var_size)
138 memset(mod_end-var_size+val_size, 0, var_size-val_size);
139 memcpy(mod_ptr, val_beg, val_size);
141 mod_end += val_size - var_size;
145 mod->mod_end = (l4_addr_t)mod_end;
150 * Handle -arg=<module_name>,blah parameter. Replace old command line
151 * parameters of <module_name> by blah. Useful for changing the boot
152 * configuration of a bootstrap image.
154 * Get a pointer to new argument and return the size.
157 get_arg_module(char *cmdline, const char *name, unsigned *size)
159 char *val_beg = NULL, *val_end;
165 while (!val_beg && (s = strstr(s, " -arg=")))
170 name_end = strchr(s, ',');
172 panic("comma missing after modname in -arg=");
177 panic("Invalid '-arg=modname,text' parameter");
179 // we do a fuzzy name-match here
181 val_beg = name_end+1;
188 unsigned char quote = 0;
189 if (*val_beg == '"' || *val_beg == '\'')
193 while (*val_end && ((!quote && !isspace(*val_end)) || *val_end!=quote))
196 *size = val_end - val_beg;