passing argc, argv and envp to main()

This commit is contained in:
Balazs Gerofi
2012-05-10 22:07:23 +09:00
parent 97d4c85195
commit 7c85ac93e8
8 changed files with 228 additions and 15 deletions

View File

@@ -191,12 +191,88 @@ void print_desc(struct program_load_desc *desc)
unsigned long dma_buf_pa;
void print_flat(char *flat)
{
char **string;
printf("counter: %d\n", *((int *)flat));
string = (char **)(flat + sizeof(int));
while (*string) {
printf("%s\n", (flat + (unsigned long)(*string)));
++string;
}
}
/*
* Flatten out a (char **) string array into the following format:
* [nr_strings][char *offset of string_0]...[char *offset of string_n-1][NULL][string0]...[stringn_1]
* if nr_strings == -1, we assume the last item is NULL
*
* NOTE: copy this string somewhere, add the address of the string to each offset
* and we get back a valid argv or envp array.
*
* returns the total length of the flat string and updates flat to
* point to the beginning.
*/
int flatten_strings(int nr_strings, char **strings, char **flat)
{
int full_len, string_i;
unsigned int flat_offset;
char *string;
char *_flat;
/* How many strings do we have? */
if (nr_strings == -1) {
for (nr_strings = 0; strings[nr_strings]; ++nr_strings);
}
/* Count full length */
full_len = sizeof(int) + sizeof(char *); // Counter and terminating NULL
for (string_i = 0; string_i < nr_strings; ++string_i) {
// Pointer + actual value
full_len += sizeof(char *) + strlen(strings[string_i]) + 1;
}
_flat = (char *)malloc(full_len);
if (!_flat) {
return 0;
}
memset(_flat, 0, full_len);
/* Number of strings */
*((int*)_flat) = nr_strings;
// Actual offset
flat_offset = sizeof(int) + sizeof(char *) * (nr_strings + 1);
for (string_i = 0; string_i < nr_strings; ++string_i) {
/* Fabricate the string */
*((char **)(_flat + sizeof(int) + string_i * sizeof(char *))) = (void *)flat_offset;
memcpy(_flat + flat_offset, strings[string_i], strlen(strings[string_i]) + 1);
flat_offset += strlen(strings[string_i]) + 1;
}
*flat = _flat;
return full_len;
}
int main(int argc, char **argv)
{
int fd, fdm;
FILE *fp;
struct program_load_desc *desc;
long r;
char *envs;
char *args;
int len;
if (argc < 2) {
fprintf(stderr, "Usage: %s (program) [args...]\n",
@@ -217,6 +293,14 @@ int main(int argc, char **argv)
}
__dprintf("# of sections: %d\n", desc->num_sections);
desc->envs_len = flatten_strings(-1, environ, &envs);
desc->envs = envs;
//print_flat(envs);
desc->args_len = flatten_strings(-1, argv + 1, &args);
desc->args = args;
//print_flat(args);
fd = open("/dev/mcos0", O_RDWR);
if (fd < 0) {

View File

@@ -31,6 +31,10 @@ struct program_load_desc {
int pid;
unsigned long entry;
unsigned long rprocess;
char *args;
unsigned long args_len;
char *envs;
unsigned long envs_len;
struct program_image_section sections[0];
};

View File

@@ -24,6 +24,7 @@ static long mcexec_prepare_image(aal_os_t os,
{
struct program_load_desc desc, *pdesc;
struct ikc_scd_packet isp;
void *args, *envs;
if (copy_from_user(&desc, udesc,
sizeof(struct program_load_desc))) {
@@ -46,6 +47,28 @@ static long mcexec_prepare_image(aal_os_t os,
pdesc->pid = task_tgid_vnr(current);
args = kmalloc(pdesc->args_len, GFP_KERNEL);
if (copy_from_user(args, pdesc->args, pdesc->args_len)) {
kfree(args);
kfree(pdesc);
return -EFAULT;
}
envs = kmalloc(pdesc->envs_len, GFP_KERNEL);
if (copy_from_user(envs, pdesc->envs, pdesc->envs_len)) {
kfree(envs);
kfree(args);
kfree(pdesc);
return -EFAULT;
}
pdesc->args = virt_to_phys(args);
printk("args: 0x%lX\n", pdesc->args);
printk("argc: %d\n", *(int*)args);
pdesc->envs = virt_to_phys(envs);
printk("envs: 0x%lX\n", pdesc->envs);
printk("envc: %d\n", *(int*)envs);
isp.msg = SCD_MSG_PREPARE_PROCESS;
isp.ref = pdesc->cpu;
isp.arg = virt_to_phys(pdesc);
@@ -62,6 +85,8 @@ static long mcexec_prepare_image(aal_os_t os,
sizeof(struct program_image_section) * desc.num_sections);
kfree(pdesc);
kfree(envs);
kfree(args);
return 0;
}