Fix FreeBSD loader API so that it works on both 32-bit and 64-bit targets.
authorStanislav Galabov <sgalabov@gmail.com>
Wed, 17 Feb 2016 13:23:31 +0000 (15:23 +0200)
committerDaniel Schwierzeck <daniel.schwierzeck@gmail.com>
Fri, 20 May 2016 23:25:50 +0000 (01:25 +0200)
Specifically tested on MIPS under QEMU (works with all  combination of bit-ness and endian-ness)

Signed-off-by: Stanislav Galabov <sgalabov@gmail.com>
api/api.c
examples/api/Makefile
examples/api/crt0.S
examples/api/glue.c

index 457dc36f6fc4e76a9ff5356414e9c0ba67fe7466..8a1433af78a98357f8e7ac58773c2b32a49aebad 100644 (file)
--- a/api/api.c
+++ b/api/api.c
@@ -52,7 +52,7 @@ static int API_getc(va_list ap)
 {
        int *c;
 
-       if ((c = (int *)va_arg(ap, u_int32_t)) == NULL)
+       if ((c = (int *)va_arg(ap, uintptr_t)) == NULL)
                return API_EINVAL;
 
        *c = getc();
@@ -68,7 +68,7 @@ static int API_tstc(va_list ap)
 {
        int *t;
 
-       if ((t = (int *)va_arg(ap, u_int32_t)) == NULL)
+       if ((t = (int *)va_arg(ap, uintptr_t)) == NULL)
                return API_EINVAL;
 
        *t = tstc();
@@ -84,7 +84,7 @@ static int API_putc(va_list ap)
 {
        char *c;
 
-       if ((c = (char *)va_arg(ap, u_int32_t)) == NULL)
+       if ((c = (char *)va_arg(ap, uintptr_t)) == NULL)
                return API_EINVAL;
 
        putc(*c);
@@ -100,7 +100,7 @@ static int API_puts(va_list ap)
 {
        char *s;
 
-       if ((s = (char *)va_arg(ap, u_int32_t)) == NULL)
+       if ((s = (char *)va_arg(ap, uintptr_t)) == NULL)
                return API_EINVAL;
 
        puts(s);
@@ -132,7 +132,7 @@ static int API_get_sys_info(va_list ap)
 {
        struct sys_info *si;
 
-       si = (struct sys_info *)va_arg(ap, u_int32_t);
+       si = (struct sys_info *)va_arg(ap, uintptr_t);
        if (si == NULL)
                return API_ENOMEM;
 
@@ -148,7 +148,7 @@ static int API_udelay(va_list ap)
 {
        unsigned long *d;
 
-       if ((d = (unsigned long *)va_arg(ap, u_int32_t)) == NULL)
+       if ((d = (unsigned long *)va_arg(ap, unsigned long)) == NULL)
                return API_EINVAL;
 
        udelay(*d);
@@ -164,11 +164,11 @@ static int API_get_timer(va_list ap)
 {
        unsigned long *base, *cur;
 
-       cur = (unsigned long *)va_arg(ap, u_int32_t);
+       cur = (unsigned long *)va_arg(ap, unsigned long);
        if (cur == NULL)
                return API_EINVAL;
 
-       base = (unsigned long *)va_arg(ap, u_int32_t);
+       base = (unsigned long *)va_arg(ap, unsigned long);
        if (base == NULL)
                return API_EINVAL;
 
@@ -199,7 +199,7 @@ static int API_dev_enum(va_list ap)
        struct device_info *di;
 
        /* arg is ptr to the device_info struct we are going to fill out */
-       di = (struct device_info *)va_arg(ap, u_int32_t);
+       di = (struct device_info *)va_arg(ap, uintptr_t);
        if (di == NULL)
                return API_EINVAL;
 
@@ -233,7 +233,7 @@ static int API_dev_open(va_list ap)
        int err = 0;
 
        /* arg is ptr to the device_info struct */
-       di = (struct device_info *)va_arg(ap, u_int32_t);
+       di = (struct device_info *)va_arg(ap, uintptr_t);
        if (di == NULL)
                return API_EINVAL;
 
@@ -265,7 +265,7 @@ static int API_dev_close(va_list ap)
        int err = 0;
 
        /* arg is ptr to the device_info struct */
-       di = (struct device_info *)va_arg(ap, u_int32_t);
+       di = (struct device_info *)va_arg(ap, uintptr_t);
        if (di == NULL)
                return API_EINVAL;
 
@@ -319,7 +319,7 @@ static int API_dev_write(va_list ap)
        int err = 0;
 
        /* 1. arg is ptr to the device_info struct */
-       di = (struct device_info *)va_arg(ap, u_int32_t);
+       di = (struct device_info *)va_arg(ap, uintptr_t);
        if (di == NULL)
                return API_EINVAL;
 
@@ -329,12 +329,12 @@ static int API_dev_write(va_list ap)
                return API_ENODEV;
 
        /* 2. arg is ptr to buffer from where to get data to write */
-       buf = (void *)va_arg(ap, u_int32_t);
+       buf = (void *)va_arg(ap, uintptr_t);
        if (buf == NULL)
                return API_EINVAL;
 
        /* 3. arg is length of buffer */
-       len = (int *)va_arg(ap, u_int32_t);
+       len = (int *)va_arg(ap, uintptr_t);
        if (len == NULL)
                return API_EINVAL;
        if (*len <= 0)
@@ -387,7 +387,7 @@ static int API_dev_read(va_list ap)
        int *len_net, *act_len_net;
 
        /* 1. arg is ptr to the device_info struct */
-       di = (struct device_info *)va_arg(ap, u_int32_t);
+       di = (struct device_info *)va_arg(ap, uintptr_t);
        if (di == NULL)
                return API_EINVAL;
 
@@ -397,23 +397,23 @@ static int API_dev_read(va_list ap)
                return API_ENODEV;
 
        /* 2. arg is ptr to buffer from where to put the read data */
-       buf = (void *)va_arg(ap, u_int32_t);
+       buf = (void *)va_arg(ap, uintptr_t);
        if (buf == NULL)
                return API_EINVAL;
 
        if (di->type & DEV_TYP_STOR) {
                /* 3. arg - ptr to var with # of blocks to read */
-               len_stor = (lbasize_t *)va_arg(ap, u_int32_t);
+               len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
                if (!len_stor)
                        return API_EINVAL;
                if (*len_stor <= 0)
                        return API_EINVAL;
 
                /* 4. arg - ptr to var with start block */
-               start = (lbastart_t *)va_arg(ap, u_int32_t);
+               start = (lbastart_t *)va_arg(ap, uintptr_t);
 
                /* 5. arg - ptr to var where to put the len actually read */
-               act_len_stor = (lbasize_t *)va_arg(ap, u_int32_t);
+               act_len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
                if (!act_len_stor)
                        return API_EINVAL;
 
@@ -422,14 +422,14 @@ static int API_dev_read(va_list ap)
        } else if (di->type & DEV_TYP_NET) {
 
                /* 3. arg points to the var with length of packet to read */
-               len_net = (int *)va_arg(ap, u_int32_t);
+               len_net = (int *)va_arg(ap, uintptr_t);
                if (!len_net)
                        return API_EINVAL;
                if (*len_net <= 0)
                        return API_EINVAL;
 
                /* 4. - ptr to var where to put the len actually read */
-               act_len_net = (int *)va_arg(ap, u_int32_t);
+               act_len_net = (int *)va_arg(ap, uintptr_t);
                if (!act_len_net)
                        return API_EINVAL;
 
@@ -453,9 +453,9 @@ static int API_env_get(va_list ap)
 {
        char *name, **value;
 
-       if ((name = (char *)va_arg(ap, u_int32_t)) == NULL)
+       if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
                return API_EINVAL;
-       if ((value = (char **)va_arg(ap, u_int32_t)) == NULL)
+       if ((value = (char **)va_arg(ap, uintptr_t)) == NULL)
                return API_EINVAL;
 
        *value = getenv(name);
@@ -476,9 +476,9 @@ static int API_env_set(va_list ap)
 {
        char *name, *value;
 
-       if ((name = (char *)va_arg(ap, u_int32_t)) == NULL)
+       if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
                return API_EINVAL;
-       if ((value = (char *)va_arg(ap, u_int32_t)) == NULL)
+       if ((value = (char *)va_arg(ap, uintptr_t)) == NULL)
                return API_EINVAL;
 
        setenv(name, value);
@@ -498,9 +498,9 @@ static int API_env_enum(va_list ap)
        int i, n;
        char *last, **next;
 
-       last = (char *)va_arg(ap, u_int32_t);
+       last = (char *)va_arg(ap, unsigned long);
 
-       if ((next = (char **)va_arg(ap, u_int32_t)) == NULL)
+       if ((next = (char **)va_arg(ap, uintptr_t)) == NULL)
                return API_EINVAL;
 
        if (last == NULL)
@@ -662,14 +662,14 @@ void api_init(void)
        }
 
        setenv_hex("api_address", (unsigned long)sig);
-       debugf("API sig @ 0x%08x\n", sig);
+       debugf("API sig @ 0x%lX\n", (unsigned long)sig);
        memcpy(sig->magic, API_SIG_MAGIC, 8);
        sig->version = API_SIG_VERSION;
        sig->syscall = &syscall;
        sig->checksum = 0;
        sig->checksum = crc32(0, (unsigned char *)sig,
                              sizeof(struct api_signature));
-       debugf("syscall entry: 0x%08x\n", sig->syscall);
+       debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall);
 }
 
 void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,
index 4e9b8ea17dcc6ffd49c34de6ec6a0febd2e36028..6cffee74652f944d9d9bc9ed812b4177432f98af 100644 (file)
@@ -11,8 +11,12 @@ ifeq ($(ARCH),arm)
 LOAD_ADDR = 0x1000000
 endif
 ifeq ($(ARCH),mips)
+ifdef CONFIG_64BIT
+LOAD_ADDR = 0xffffffff80200000
+else
 LOAD_ADDR = 0x80200000
 endif
+endif
 
 # Resulting ELF and binary exectuables will be named demo and demo.bin
 extra-y = demo
index ced2c82e5ffcacb5702cd0a9a841a559cad8d74e..5a7049d6b4b721f71a85948364d24217e93030ec 100644 (file)
@@ -41,28 +41,29 @@ syscall:
        ldr     pc, [ip]
 
 #elif defined(CONFIG_MIPS)
+#include <asm/asm.h>
        .text
        .globl __start
        .ent __start
 __start:
-       sw      $sp, search_hint
+       PTR_S   $sp, search_hint
        b       main
        .end __start
 
        .globl syscall
        .ent syscall
 syscall:
-       sw      $ra, return_addr
-       lw      $t9, syscall_ptr
+       PTR_S   $ra, return_addr
+       PTR_L   $t9, syscall_ptr
        jalr    $t9
        nop
-       lw      $ra, return_addr
+       PTR_L   $ra, return_addr
        jr      $ra
        nop
        .end syscall
 
 return_addr:
-       .align 4
+       .align 8
        .long 0
 #else
 #error No support for this arch!
@@ -70,7 +71,7 @@ return_addr:
 
        .globl syscall_ptr
 syscall_ptr:
-       .align  4
+       .align  8
        .long   0
 
        .globl search_hint
index d619518d42a64a19c0ba6ea61e0c0b1c9cd930f6..8aabf32c899acb2e3c8990db52e16f235f68c0a2 100644 (file)
@@ -77,7 +77,7 @@ int ub_getc(void)
 {
        int c;
 
-       if (!syscall(API_GETC, NULL, (uint32_t)&c))
+       if (!syscall(API_GETC, NULL, &c))
                return -1;
 
        return c;
@@ -87,7 +87,7 @@ int ub_tstc(void)
 {
        int t;
 
-       if (!syscall(API_TSTC, NULL, (uint32_t)&t))
+       if (!syscall(API_TSTC, NULL, &t))
                return -1;
 
        return t;
@@ -95,12 +95,12 @@ int ub_tstc(void)
 
 void ub_putc(char c)
 {
-       syscall(API_PUTC, NULL, (uint32_t)&c);
+       syscall(API_PUTC, NULL, &c);
 }
 
 void ub_puts(const char *s)
 {
-       syscall(API_PUTS, NULL, (uint32_t)s);
+       syscall(API_PUTS, NULL, s);
 }
 
 /****************************************
@@ -126,7 +126,7 @@ struct sys_info * ub_get_sys_info(void)
        si.mr_no = UB_MAX_MR;
        memset(&mr, 0, sizeof(mr));
 
-       if (!syscall(API_GET_SYS_INFO, &err, (u_int32_t)&si))
+       if (!syscall(API_GET_SYS_INFO, &err, &si))
                return NULL;
 
        return ((err) ? NULL : &si);
@@ -344,7 +344,7 @@ char * ub_env_get(const char *name)
 {
        char *value;
 
-       if (!syscall(API_ENV_GET, NULL, (uint32_t)name, (uint32_t)&value))
+       if (!syscall(API_ENV_GET, NULL, name, &value))
                return NULL;
 
        return value;
@@ -352,7 +352,7 @@ char * ub_env_get(const char *name)
 
 void ub_env_set(const char *name, char *value)
 {
-       syscall(API_ENV_SET, NULL, (uint32_t)name, (uint32_t)value);
+       syscall(API_ENV_SET, NULL, name, value);
 }
 
 static char env_name[256];
@@ -369,7 +369,7 @@ const char * ub_env_enum(const char *last)
         * 'name=val' string), since the API_ENUM_ENV call uses envmatch()
         * internally, which handles such case
         */
-       if (!syscall(API_ENV_ENUM, NULL, (uint32_t)last, (uint32_t)&env))
+       if (!syscall(API_ENV_ENUM, NULL, last, &env))
                return NULL;
 
        if (!env)
@@ -396,7 +396,7 @@ int ub_display_get_info(int type, struct display_info *di)
 {
        int err = 0;
 
-       if (!syscall(API_DISPLAY_GET_INFO, &err, (uint32_t)type, (uint32_t)di))
+       if (!syscall(API_DISPLAY_GET_INFO, &err, type, di))
                return API_ESYSC;
 
        return err;