Bare-metal Loader - 通过共享内存将.elf二进制文件发送到其他处理器并执行

时间:2013-11-28 13:01:07

标签: c linux elf bare-metal

设定: 一个运行busybox-Linux的ARM-CPU(A9)。这个与网络对话并获得预编译的静态链接精灵。 第二个CPU运行裸机应用程序。我在那个上面有newlib,整个“OS”只是执行那个基本程序而在内存中。 两者都分享OCM。

我成功地使两个处理器“对话”。我可以从linux中将十六进制值写入内存,另一个处理器读取它,反之亦然。 现在我想解析前面提到的精灵,将它发送到OCM,让裸机读入它的内存,通过asm设置程序计数器并执行所述elf(也可以使用.o文件)。 我已经陷入了解析精灵的问题......

#include <sys/types.h>                                                                                                                    
#include <sys/stat.h>                                                                                                                     
#include <fcntl.h>                                                                                                                        
#include <byteswap.h>                                                                                                                     
#include <unistd.h>                                                                                                                       
#include <stdlib.h>                                                                                                                       
#include <stdio.h>                                                                                                                        
#include <stdint.h>                                                                                                                       
#include <errno.h>                                                                                                                        
#include <sys/mman.h>                                                                                                                     

#define PAGE_SIZE ((size_t)getpagesize())                                                                                                 
#define PAGE_MASK ((uint64_t)(long)~(PAGE_SIZE - 1))                                                                                      

const unsigned int COMM_RX_DATA  = 0xFFFF900c;                                                                                            

int main(int argc, char **argv){                                                                                                          

    int     fd;                                                                                                                           
    int cached = 0;                                                                                                                       
    unsigned char* c;                                                                                                                     
    //uint32_t value;                                                                                                                     
    unsigned char value;                                                                                                                  
    uint64_t offset = COMM_RX_DATA;                                                                                                       
    uint64_t base;                                                                                                                        
    volatile uint8_t *mm;                                                                                                                 


    fprintf(stderr, "Nr. 0\n");                                                                                                           

    FILE* f_read;                                                                                                                         

    if ((argc != 1) && (argc != 2)) {                                                                                                     
        fprintf(stderr, "usage: %s  ELF_NAME\n", argv[0]);                                                                                
        return 1;                                                                                                                         
    }                                                                                                                                     

  fd = open("/dev/mem", O_RDWR);//|(!cached ? O_SYNC : 0));                                                                               
    if (fd < 0) {                                                                                                                         
        fprintf(stderr, "open(/dev/mem) failed (%d)\n", errno);                                                                           
        return 1;                                                                                                                         
    }                                                                                                                                     


    f_read = fopen(argv[1], "rb");                                                                                                        
    if(!f_read){                                                                                                                          
        fprintf(stderr, "read failed");                                                                                                   
        return 1;                                                                                                                         
    }                                                                                                                                     

    else {                                                                                                                                
        printf("Nr. 1\n");                                                                                                                
        base = offset & PAGE_MASK;                                                                                                        
        offset &= ~PAGE_MASK;                                                                                                             

        mm = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, base);                                                         

        fseek(f_read, 0, SEEK_END);                                                                                                       
        int size = ftell(f_read);                                                                                                         
        fseek(f_read, 0, SEEK_SET); //Reset stream                                                                                        
        c = malloc(size);                                                                                                                 
        //malloc error checking!                                                                                                          

        while (fgets(c, size, f_read) != NULL ){ //tried fgetc but segfaults                                                              
            //tmp-output to stdout                                                                                                        
            puts(c);                                                                                                                      
            value = c;//strtoull((char*)c, NULL, 0);                                                                                      
            printf("Writing %d to %d", (int)value, (int)(mm + offset));                                                                   
            *(volatile uint32_t *)(mm + offset) = value;                                                                                  
            printf("size: %d , value = %s\n", size, value);                                                                               
        }                                                                                                                                 

    }                                                                                                                                     
    munmap((void *)mm, PAGE_SIZE);                                                                                                        
    fclose(f_read);                                                                                                                       

    return 0;                                                                                                                             
}                                                                                            

_asm-idea.S:

ExecuteR0:
        mov  lr, r0 /* move the destination address into link register */

        mcr  15,0,r0,cr7,cr5,0      /* Invalidate Instruction cache */
        mcr  15,0,r0,cr7,cr5,6      /* Invalidate branch predictor array */

        dsb
        isb                 /* make sure it completes */

    ldr r4, =0
        mcr  15,0,r4,cr1,cr0,0      /* disable the ICache and MMU */

        isb                 /* make sure it completes */


        bx      lr  /* force the switch, destination should have been in r0 */

帮助我强大你是我唯一的希望。

0 个答案:

没有答案