Subversion Repositories Kolibri OS

Rev

Rev 892 | Rev 908 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1.  
  2. #include <types.h>
  3. #include <core.h>
  4. #include <spinlock.h>
  5. #include <link.h>
  6. #include <mm.h>
  7. #include <slab.h>
  8. #include <pe.h>
  9.  
  10. int __stdcall strncmp(const char *s1, const char *s2, size_t n);
  11.  
  12. extern int __stdcall mnt_exec(void *raw, size_t raw_size, char *path,
  13.               char *cmdline, u32_t flags) asm ("mnt_exec");
  14.  
  15. static dll_t core_dll;
  16.  
  17. static char* strupr(char *str )
  18. {
  19.     char *p;
  20.     unsigned char c;
  21.  
  22.     p = str;
  23.     while( (c = *p) )
  24.     {
  25.         if( c >= 'a' && c <= 'z' )
  26.             *p = c - 'a' + 'A';
  27.         ++p;
  28.     }
  29.  
  30.     return( str );
  31. }
  32.  
  33. void * memcpy(void * _dest, const void *_src, size_t _n)
  34. {
  35. int d0, d1, d2;
  36.  __asm__ __volatile__(
  37.         "rep ; movsl\n\t"
  38.         "testb $2,%b4\n\t"
  39.         "je 1f\n\t"
  40.         "movsw\n"
  41.         "1:\ttestb $1,%b4\n\t"
  42.         "je 2f\n\t"
  43.         "movsb\n"
  44.         "2:"
  45.         : "=&c" (d0), "=&D" (d1), "=&S" (d2)
  46.         :"0" (_n/4), "q" (_n),"1" ((long)_dest),"2" ((long)_src)
  47.         : "memory");
  48.  return (_dest);
  49. }
  50.  
  51. size_t strlen(const char *str)
  52. {
  53. int d0;
  54. register int __res;
  55. __asm__ __volatile__(
  56.         "repne\n\t"
  57.         "scasb\n\t"
  58.         "notl %0\n\t"
  59.         "decl %0"
  60.         :"=c" (__res), "=&D" (d0) :"1" (str),"a" (0), "0" (0xffffffff));
  61. return __res;
  62. }
  63.  
  64. void init_core_dll()
  65. {
  66.     PIMAGE_DOS_HEADER        dos;
  67.     PIMAGE_NT_HEADERS32      nt;
  68.     PIMAGE_EXPORT_DIRECTORY  exp;
  69.  
  70.     dos =  (PIMAGE_DOS_HEADER)LOAD_BASE;
  71.     nt  =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  72.     exp =  MakePtr(PIMAGE_EXPORT_DIRECTORY,LOAD_BASE,
  73.                    nt->OptionalHeader.DataDirectory[0].VirtualAddress);
  74.  
  75.     list_initialize(&core_dll.link);
  76.  
  77.     core_dll.img_base = LOAD_BASE;
  78.     core_dll.img_size = nt->OptionalHeader.SizeOfImage;
  79.     core_dll.img_md   = NULL;
  80.  
  81.     core_dll.img_hdr  = nt;
  82.     core_dll.img_sec  = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32));
  83.     core_dll.img_exp  = MakePtr(PIMAGE_EXPORT_DIRECTORY,LOAD_BASE,
  84.                         nt->OptionalHeader.DataDirectory[0].VirtualAddress);
  85.     core_dll.img_name = strupr(MakePtr(char*, LOAD_BASE, exp->Name));
  86.  
  87.     DBG("%s base %x size %x sections %d exports %x\n",
  88.         core_dll.img_name, core_dll.img_base,
  89.         core_dll.img_size, nt->FileHeader.NumberOfSections,
  90.         core_dll.img_exp );
  91. };
  92.  
  93.  
  94. dll_t * find_dll(const char *name)
  95. {
  96.     dll_t* dll = &core_dll;
  97.  
  98.     do
  99.     {
  100.         if( !strncmp(name,dll->img_name,16))
  101.             return dll;
  102.  
  103.         dll = (dll_t*)dll->link.next;
  104.  
  105.     }while(&dll->link !=  &core_dll.link);
  106.  
  107.     return NULL;
  108. };
  109.  
  110.  
  111. typedef struct
  112. {
  113.   char         srv_name[16];  //        ASCIIZ string
  114.   u32_t        magic;         // +0x10  'SRV '
  115.   size_t       size;          // +0x14  size of structure SRV
  116.   void        *fd;            // +0x18  next SRV descriptor
  117.   void        *bk;            // +0x1C  prev SRV descriptor
  118.   addr_t       base;          // +0x20  service base address
  119.   addr_t       entry;         // +0x24  service START function
  120.   void        *srv_proc;      // +0x28  main service handler
  121. }srv_t;
  122.  
  123. typedef srv_t* __stdcall  drv_entry_t(int);
  124.  
  125. srv_t* __fastcall load_pe_driver(const char *path)
  126. {
  127.     PIMAGE_DOS_HEADER     dos;
  128.     PIMAGE_NT_HEADERS32   nt;
  129.  
  130.     drv_entry_t   *drv_entry;
  131.     md_t          *md;
  132.     srv_t         *srv;
  133.  
  134.     md = load_image(path);
  135.  
  136.     if( ! md )
  137.         return 0;
  138.  
  139.     if( link_image( md->base ) )
  140.     {
  141.         dos = (PIMAGE_DOS_HEADER)md->base;
  142.         nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  143.  
  144.         drv_entry = MakePtr(drv_entry_t*, md->base,
  145.                             nt->OptionalHeader.AddressOfEntryPoint);
  146.  
  147.         srv = drv_entry(1);
  148.  
  149.         if(srv != NULL)
  150.             srv->entry = nt->OptionalHeader.AddressOfEntryPoint + md->base;
  151.  
  152.         return srv;
  153.     }
  154.     else
  155.     {
  156.         md_free( md );
  157.         return NULL;
  158.     }
  159. }
  160.  
  161. typedef struct
  162. {
  163.     int a_type;
  164.     union
  165.     {
  166.         long  a_val;
  167.         void *a_ptr;
  168.         void  (*a_fcn)( ) ;
  169.     }a_un;
  170. }auxv_t;
  171.  
  172. #define AUX_COUNT       0
  173.  
  174. typedef struct
  175. {
  176.     int     argc;       /*  always 2                                */
  177.     char   *path;       /*  argv[0]   program path                  */
  178.     char   *cmdline;    /*  argv[1]   command  line. May be null    */
  179.     u32_t   sep1;       /*  separator.  must be zero                */
  180.     char   *env;        /*  single environment string               */
  181.     u32_t   sep2;       /*  separator.  must be zero                */
  182.     auxv_t  aux[1];     /*  aux. AT_NULL for now                    */
  183. }exec_stack_t;
  184.  
  185.  
  186. addr_t new_app_space(void);
  187.  
  188. int __stdcall pe_app_param(char *path, void *raw, addr_t ex_pg_dir,
  189.                           addr_t ex_stack_page) asm ("pe_app_param");
  190.  
  191. int sys_exec(char *path, char *cmdline, u32_t flags)
  192. {
  193.     addr_t        ex_pg_dir;
  194.     addr_t        ex_stack_tab;
  195.     addr_t        ex_stack_page;
  196.     addr_t        ex_pl0_stack;
  197.  
  198.     exec_stack_t *ex_stack;
  199.     int           stack_size;
  200.     char         *ex_path;
  201.     char         *ex_cmdline = NULL;
  202.  
  203.     size_t        raw_size;
  204.     u32_t        *raw;
  205.  
  206.     int pathsize = 0;
  207.     int cmdsize  = 0;
  208.     int envsize  = 0;
  209.  
  210.     u32_t tmp;
  211.  
  212.     DBG("\nexec %s cmd %s flags %x\n", path, cmdline, flags);
  213.  
  214.     if( ! path)
  215.     {
  216.         DBG("invalid path\n");
  217.         return;
  218.     };
  219.  
  220.     raw = load_file(path, &raw_size);
  221.  
  222.     if( ! raw )
  223.         return -5;                                      /* FIXME */
  224.  
  225.     if( (raw[0] == 0x554E454D) &&
  226.         ( ( raw[1] == 0x31305445) ||
  227.           ( raw[1] == 0x30305445) ) )
  228.  
  229.     {
  230.         DBG("leagacy Kolibri application\n");
  231.         int tmp =  mnt_exec(raw, raw_size, path, cmdline, flags);
  232.         return tmp;
  233.     }
  234.  
  235.     if( ! validate_pe(raw, raw_size) )
  236.     {
  237.         DBG("invalid executable file %s\n", path);
  238.         mem_free(raw);
  239.         return -31;
  240.     }
  241.  
  242.     pathsize = strlen(path)+1;
  243.  
  244.     if( cmdline )
  245.         cmdsize = strlen(cmdline)+1;
  246.  
  247.     stack_size = sizeof(exec_stack_t) + pathsize +
  248.                  cmdsize + envsize + AUX_COUNT*sizeof(auxv_t);
  249.  
  250.     stack_size = (stack_size + 15) & ~15;               /* keep stack aligned */
  251.  
  252.     DBG("stacksize %d\n", stack_size);
  253.  
  254.     if( stack_size > 4096 )
  255.     {
  256.         DBG("command line too long\n");
  257.         return -30;
  258.     }
  259.  
  260.     ex_pg_dir      = new_app_space();
  261.  
  262.     if( !ex_pg_dir )
  263.     {
  264.         mem_free(raw);
  265.         return -30;                                    /* FIXME          */
  266.     };
  267.  
  268.     ex_stack_tab   = ex_pg_dir + 4096;
  269.     ex_pl0_stack   = ex_pg_dir + 4096 * 2;
  270.  
  271.     ex_stack_page  = core_alloc(0);                    /* 2^0 = 1 page   */
  272.  
  273.     if( ! ex_stack_page )
  274.     {
  275.         core_free(ex_stack_tab);
  276.         mem_free(raw);
  277.         return -30;                                    /* FIXME          */
  278.     };
  279.  
  280.     __asm__ __volatile__ (
  281.     "xorl %%eax, %%eax      \n\t"
  282.     "rep stosl"
  283.     :"=c"(tmp),"=D"(tmp)
  284.     :"c"(1024),"D"(ex_stack_page + OS_BASE)
  285.     :"eax","cc");
  286.  
  287.     ((u32_t*)(ex_stack_tab+OS_BASE))[1023] = ex_stack_page | 7;
  288.  
  289.     ex_stack = (exec_stack_t*)(ex_stack_page + OS_BASE
  290.                                + PAGE_SIZE - stack_size);
  291.     ex_stack->argc = 2;
  292.  
  293.     ex_path = MakePtr(char*, ex_stack, sizeof(exec_stack_t)+AUX_COUNT*sizeof(auxv_t));
  294.  
  295.     memcpy(ex_path, path, pathsize);
  296.     ex_stack->path = (char*)(((addr_t)ex_path & 0xFFF) + 0x7FCFF000);  /* top of stack */
  297.  
  298.     if( cmdline )
  299.     {
  300.         ex_cmdline = ex_path + pathsize;
  301.         memcpy(ex_cmdline, cmdline, cmdsize);
  302.         ex_stack->cmdline = ex_stack->path + pathsize;
  303.     };
  304.  
  305. /*
  306.     ex_stack.env = null
  307.     ex_stack.aux[0] = AT_NULL
  308.  */
  309.  
  310.     DBG("create stack at %x\n\tpath %x\n\tcmdline %x\n",
  311.          ex_stack, ex_stack->path, ex_stack->cmdline);
  312.  
  313.     pe_app_param(path, raw, ex_pg_dir, ex_stack_page);
  314.     return 0;
  315. };
  316.  
  317. #define  master_tab    (page_tabs+ (page_tabs>>10))
  318.  
  319. void sys_app_entry(addr_t raw, addr_t ex_stack)
  320. {
  321.     PIMAGE_DOS_HEADER     dos;
  322.     PIMAGE_NT_HEADERS32   nt;
  323.  
  324.     size_t   img_size;
  325.     count_t  img_pages;
  326.     count_t  img_tabs;
  327.     count_t  i;
  328.     u32_t    tmp;
  329.  
  330.     __asm__ __volatile__ ("sti");
  331.  
  332.     DBG("pe_app_entry: raw %x esp %x\n", raw, ex_stack);
  333.  
  334.     dos = (PIMAGE_DOS_HEADER)raw;
  335.     nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  336.  
  337.     img_size  =  nt->OptionalHeader.SizeOfImage;
  338.  
  339.     img_pages = img_size >> 12;
  340.     img_tabs  = ((img_size + 0x3FFFFF) & ~0x3FFFFF) >> 22;
  341.  
  342.     DBG("app pages %d app tabs %d\n", img_pages, img_tabs);
  343.  
  344.     for(i = 0; i < img_tabs; i++)
  345.     {
  346.         addr_t tab = core_alloc(0);
  347.         ((u32_t*)master_tab)[i] = tab|7;                            /*   FIXME     */
  348.     }
  349.  
  350.     ((u32_t*)master_tab)[0x7FC/4] = (ex_stack & 0xFFFFF000)|7;                                /*   FIXME     */
  351.  
  352.     __asm__ __volatile__ (
  353.     "xorl %%eax, %%eax      \n\t"
  354.     "rep stosl"
  355.     :"=c"(tmp),"=D"(tmp)
  356.     :"c"(img_tabs<<10),"D"(page_tabs)
  357.     :"eax","cc");
  358.  
  359.     for(i = 0; i < img_pages; i++)
  360.     {
  361.         addr_t page = core_alloc(0);
  362.         ((u32_t*)page_tabs)[i] = page | 7;                          /*   FIXME     */
  363.     }
  364.  
  365.     create_image(0, raw);
  366.  
  367.     __asm__ __volatile__ (
  368.     "xchgw %bx, %bx");
  369.  
  370.     addr_t entry = nt->OptionalHeader.AddressOfEntryPoint +
  371.                    nt->OptionalHeader.ImageBase;
  372.  
  373.   //  __asm__ __volatile__ (
  374.   //  "call %0":: "r" (entry));
  375.  
  376.     while(1);
  377.  
  378. };
  379.