module.c 60.0 KB
Newer Older
qiuyiuestc's avatar
qiuyiuestc 已提交
1 2 3
/*
 * File      : module.c
 * This file is part of RT-Thread RTOS
D
dzzxzz 已提交
4
 * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
qiuyiuestc's avatar
qiuyiuestc 已提交
5
 *
B
Bernard Xiong 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
qiuyiuestc's avatar
qiuyiuestc 已提交
19 20
 *
 * Change Logs:
D
dzzxzz 已提交
21 22 23 24 25 26
 * Date           Author       Notes
 * 2010-01-09     Bernard      first version
 * 2010-04-09     yi.qiu       implement based on first version
 * 2010-10-23     yi.qiu       implement module memory allocator
 * 2011-05-25     yi.qiu       implement module hook function
 * 2011-06-23     yi.qiu       rewrite module memory allocator
27
 * 2012-11-23     Bernard      using RT_DEBUG_LOG instead of rt_kprintf.
B
Bernard Xiong 已提交
28
 * 2012-11-28     Bernard      remove rt_current_module and user
29
 *                             can use rt_module_unload to remove a module.
30
 * 2017-08-20     parai        support intel 386 machine
qiuyiuestc's avatar
qiuyiuestc 已提交
31
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
32

33
#include <rthw.h>
qiuyiuestc's avatar
qiuyiuestc 已提交
34
#include <rtthread.h>
qiuyiuestc's avatar
qiuyiuestc 已提交
35
#include <rtm.h>
qiuyiuestc's avatar
qiuyiuestc 已提交
36

37 38 39 40
#ifdef RT_USING_FINSH
#include <finsh.h>
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
41
#ifdef RT_USING_MODULE
42
#include "module.h"
qiuyiuestc's avatar
qiuyiuestc 已提交
43

44 45 46 47 48 49 50 51 52 53 54
#define elf_module        ((Elf32_Ehdr *)module_ptr)
#define shdr              ((Elf32_Shdr *)((rt_uint8_t *)module_ptr + elf_module->e_shoff))
#define phdr              ((Elf32_Phdr *)((rt_uint8_t *)module_ptr + elf_module->e_phoff))

#define IS_PROG(s)        (s.sh_type == SHT_PROGBITS)
#define IS_NOPROG(s)      (s.sh_type == SHT_NOBITS)
#define IS_REL(s)         (s.sh_type == SHT_REL)
#define IS_RELA(s)        (s.sh_type == SHT_RELA)
#define IS_ALLOC(s)       (s.sh_flags == SHF_ALLOC)
#define IS_AX(s)          ((s.sh_flags & SHF_ALLOC) && (s.sh_flags & SHF_EXECINSTR))
#define IS_AW(s)          ((s.sh_flags & SHF_ALLOC) && (s.sh_flags & SHF_WRITE))
qiuyiuestc's avatar
qiuyiuestc 已提交
55

56 57 58 59 60 61 62 63 64 65 66 67
#ifdef RT_USING_MODULE_STKSZ
#undef RT_USING_MODULE_STKSZ
#endif

#ifndef RT_USING_MODULE_STKSZ
#define RT_USING_MODULE_STKSZ (4096 * 2)
#endif

#ifndef RT_USING_MODULE_PRIO
#define RT_USING_MODULE_PRIO (RT_THREAD_PRIORITY_MAX - 2)
#endif

68
#ifdef RT_USING_SLAB
69
#define PAGE_COUNT_MAX    256
qiuyiuestc's avatar
qiuyiuestc 已提交
70

qiuyiuestc's avatar
qiuyiuestc 已提交
71 72 73
/* module memory allocator */
struct rt_mem_head
{
74 75
    rt_size_t size;                /* size of memory block */
    struct rt_mem_head *next;      /* next valid memory block */
qiuyiuestc's avatar
qiuyiuestc 已提交
76 77
};

qiuyiuestc's avatar
qiuyiuestc 已提交
78 79
struct rt_page_info
{
80 81
    rt_uint32_t *page_ptr;
    rt_uint32_t npage;
qiuyiuestc's avatar
qiuyiuestc 已提交
82 83 84
};

static void *rt_module_malloc_page(rt_size_t npages);
85 86 87
static void rt_module_free_page(rt_module_t module,
                                void       *page_ptr,
                                rt_size_t   npages);
qiuyiuestc's avatar
qiuyiuestc 已提交
88

qiuyiuestc's avatar
qiuyiuestc 已提交
89
static struct rt_semaphore mod_sem;
90 91
#endif

92
static struct rt_module_symtab *_rt_module_symtab_begin = RT_NULL;
93
static struct rt_module_symtab *_rt_module_symtab_end   = RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
94

95 96 97 98
#if defined(__IAR_SYSTEMS_ICC__) /* for IAR compiler */
    #pragma section="RTMSymTab"
#endif

99 100 101
/**
 * @ingroup SystemInit
 *
B
bernard.xiong@gmail.com 已提交
102
 * This function will initialize system module
103
 */
B
bernard 已提交
104
int rt_system_module_init(void)
105
{
106
#if defined(__GNUC__) && !defined(__CC_ARM)
107 108
    extern int __rtmsymtab_start;
    extern int __rtmsymtab_end;
109

110 111
    _rt_module_symtab_begin = (struct rt_module_symtab *)&__rtmsymtab_start;
    _rt_module_symtab_end   = (struct rt_module_symtab *)&__rtmsymtab_end;
D
dzzxzz 已提交
112
#elif defined (__CC_ARM)
113 114
    extern int RTMSymTab$$Base;
    extern int RTMSymTab$$Limit;
D
dzzxzz 已提交
115

116
    _rt_module_symtab_begin = (struct rt_module_symtab *)&RTMSymTab$$Base;
117
    _rt_module_symtab_end   = (struct rt_module_symtab *)&RTMSymTab$$Limit;
118 119
#elif defined (__IAR_SYSTEMS_ICC__)
    _rt_module_symtab_begin = __section_begin("RTMSymTab");
120
    _rt_module_symtab_end   = __section_end("RTMSymTab");
qiuyiuestc's avatar
qiuyiuestc 已提交
121
#endif
122

123
#ifdef RT_USING_SLAB
124 125
    /* initialize heap semaphore */
    rt_sem_init(&mod_sem, "module", 1, RT_IPC_FLAG_FIFO);
126
#endif
127
    return 0;
128
}
B
Bernard Xiong 已提交
129
INIT_COMPONENT_EXPORT(rt_system_module_init);
130

131 132 133 134 135 136 137 138 139 140
#ifdef RT_USING_FINSH
void list_symbol(void)
{
    /* find in kernel symbol table */
    struct rt_module_symtab *index;

    for (index = _rt_module_symtab_begin;
         index != _rt_module_symtab_end;
         index ++)
    {
141
        rt_kprintf("%s\n", index->name);
142 143 144 145 146 147 148 149
    }

    return ;
}
FINSH_FUNCTION_EXPORT(list_symbol, list symbol for module);
MSH_CMD_EXPORT(list_symbol, list symbol for module);
#endif

D
dzzxzz 已提交
150
static rt_uint32_t rt_module_symbol_find(const char *sym_str)
151
{
152 153
    /* find in kernel symbol table */
    struct rt_module_symtab *index;
154 155 156 157

    for (index = _rt_module_symtab_begin;
         index != _rt_module_symtab_end;
         index ++)
158 159 160 161 162 163
    {
        if (rt_strcmp(index->name, sym_str) == 0)
            return (rt_uint32_t)index->addr;
    }

    return 0;
164
}
qiuyiuestc's avatar
qiuyiuestc 已提交
165

qiuyiuestc's avatar
qiuyiuestc 已提交
166 167 168
/**
 * This function will return self module object
 *
qiuyiuestc's avatar
qiuyiuestc 已提交
169
 * @return the self module object
qiuyiuestc's avatar
qiuyiuestc 已提交
170
 */
D
dzzxzz 已提交
171
rt_module_t rt_module_self(void)
qiuyiuestc's avatar
qiuyiuestc 已提交
172
{
173
    rt_thread_t tid;
qiuyiuestc's avatar
qiuyiuestc 已提交
174

175 176 177
    tid = rt_thread_self();
    if (tid == RT_NULL)
        return RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
178

179 180
    /* return current module */
    return (rt_module_t)tid->module_id;
qiuyiuestc's avatar
qiuyiuestc 已提交
181
}
182
RTM_EXPORT(rt_module_self);
qiuyiuestc's avatar
qiuyiuestc 已提交
183

184 185 186
static int rt_module_arm_relocate(struct rt_module *module,
                                  Elf32_Rel        *rel,
                                  Elf32_Addr        sym_val)
qiuyiuestc's avatar
qiuyiuestc 已提交
187
{
188 189 190 191
    Elf32_Addr *where, tmp;
    Elf32_Sword addend, offset;
    rt_uint32_t upper, lower, sign, j1, j2;

192 193 194
    where = (Elf32_Addr *)((rt_uint8_t *)module->module_space
                           + rel->r_offset
                           - module->vstart_addr);
195 196 197 198 199 200
    switch (ELF32_R_TYPE(rel->r_info))
    {
    case R_ARM_NONE:
        break;
    case R_ARM_ABS32:
        *where += (Elf32_Addr)sym_val;
201 202
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_ABS32: %x -> %x\n",
                                       where, *where));
203 204 205 206 207 208 209 210 211 212 213
        break;
    case R_ARM_PC24:
    case R_ARM_PLT32:
    case R_ARM_CALL:
    case R_ARM_JUMP24:
        addend = *where & 0x00ffffff;
        if (addend & 0x00800000)
            addend |= 0xff000000;
        tmp = sym_val - (Elf32_Addr)where + (addend << 2);
        tmp >>= 2;
        *where = (*where & 0xff000000) | (tmp & 0x00ffffff);
214 215
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_PC24: %x -> %x\n",
                                       where, *where));
216 217 218
        break;
    case R_ARM_REL32:
        *where += sym_val - (Elf32_Addr)where;
219 220 221
        RT_DEBUG_LOG(RT_DEBUG_MODULE,
                     ("R_ARM_REL32: %x -> %x, sym %x, offset %x\n",
                      where, *where, sym_val, rel->r_offset));
222 223 224 225 226
        break;
    case R_ARM_V4BX:
        *where &= 0xf000000f;
        *where |= 0x01a0f000;
        break;
227 228 229 230
#ifdef MODULE_USING_386
    case R_386_GLOB_DAT:
    case R_386_JUMP_SLOT:
#endif
231 232 233
    case R_ARM_GLOB_DAT:
    case R_ARM_JUMP_SLOT:
        *where = (Elf32_Addr)sym_val;
234 235
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_JUMP_SLOT: 0x%x -> 0x%x 0x%x\n",
                                       where, *where, sym_val));
236 237 238
        break;
#if 0        /* To do */
    case R_ARM_GOT_BREL:
239
        temp   = (Elf32_Addr)sym_val;
240
        *where = (Elf32_Addr)&temp;
241 242
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_GOT_BREL: 0x%x -> 0x%x 0x%x\n",
                                       where, *where, sym_val));
243
        break;
244 245 246
#endif
#ifdef MODULE_USING_386
    case R_386_RELATIVE:
B
bernard.xiong@gmail.com 已提交
247
#endif
248 249
    case R_ARM_RELATIVE:
        *where = (Elf32_Addr)sym_val + *where;
250 251
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_RELATIVE: 0x%x -> 0x%x 0x%x\n",
                                       where, *where, sym_val));
252 253 254
        break;
    case R_ARM_THM_CALL:
    case R_ARM_THM_JUMP24:
255 256 257 258 259 260 261
        upper  = *(rt_uint16_t *)where;
        lower  = *(rt_uint16_t *)((Elf32_Addr)where + 2);

        sign   = (upper >> 10) & 1;
        j1     = (lower >> 13) & 1;
        j2     = (lower >> 11) & 1;
        offset = (sign << 24) |
262 263 264 265
                 ((~(j1 ^ sign) & 1) << 23) |
                 ((~(j2 ^ sign) & 1) << 22) |
                 ((upper & 0x03ff) << 12) |
                 ((lower & 0x07ff) << 1);
266
        if (offset & 0x01000000)
267
            offset -= 0x02000000;
268 269
        offset += sym_val - (Elf32_Addr)where;

270 271 272
        if (!(offset & 1) ||
            offset <= (rt_int32_t)0xff000000 ||
            offset >= (rt_int32_t)0x01000000)
273
        {
274
            rt_kprintf("Module: Only Thumb addresses allowed\n");
275

276 277 278 279
            return -1;
        }

        sign = (offset >> 24) & 1;
280 281 282
        j1   = sign ^ (~(offset >> 23) & 1);
        j2   = sign ^ (~(offset >> 22) & 1);
        *(rt_uint16_t *)where = (rt_uint16_t)((upper & 0xf800) |
283 284
                                              (sign << 10) |
                                              ((offset >> 12) & 0x03ff));
285
        *(rt_uint16_t *)(where + 2) = (rt_uint16_t)((lower & 0xd000) |
286 287
                                                    (j1 << 13) | (j2 << 11) |
                                                    ((offset >> 1) & 0x07ff));
288 289 290 291 292 293 294 295
        upper = *(rt_uint16_t *)where;
        lower = *(rt_uint16_t *)((Elf32_Addr)where + 2);
        break;
    default:
        return -1;
    }

    return 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
296 297
}

B
bernard 已提交
298
void rt_module_init_object_container(struct rt_module *module)
qiuyiuestc's avatar
qiuyiuestc 已提交
299
{
300
    RT_ASSERT(module != RT_NULL);
qiuyiuestc's avatar
qiuyiuestc 已提交
301

302 303 304
    /* clear all of object information */
    rt_memset(&module->module_object[0], 0x0, sizeof(module->module_object));

305 306 307 308
    /* initialize object container - thread */
    rt_list_init(&(module->module_object[RT_Object_Class_Thread].object_list));
    module->module_object[RT_Object_Class_Thread].object_size = sizeof(struct rt_thread);
    module->module_object[RT_Object_Class_Thread].type = RT_Object_Class_Thread;
qiuyiuestc's avatar
qiuyiuestc 已提交
309

310
#ifdef RT_USING_SEMAPHORE
311 312 313 314
    /* initialize object container - semaphore */
    rt_list_init(&(module->module_object[RT_Object_Class_Semaphore].object_list));
    module->module_object[RT_Object_Class_Semaphore].object_size = sizeof(struct rt_semaphore);
    module->module_object[RT_Object_Class_Semaphore].type = RT_Object_Class_Semaphore;
315
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
316

317
#ifdef RT_USING_MUTEX
318 319 320 321
    /* initialize object container - mutex */
    rt_list_init(&(module->module_object[RT_Object_Class_Mutex].object_list));
    module->module_object[RT_Object_Class_Mutex].object_size = sizeof(struct rt_mutex);
    module->module_object[RT_Object_Class_Mutex].type = RT_Object_Class_Mutex;
322
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
323

324
#ifdef RT_USING_EVENT
325 326 327 328
    /* initialize object container - event */
    rt_list_init(&(module->module_object[RT_Object_Class_Event].object_list));
    module->module_object[RT_Object_Class_Event].object_size = sizeof(struct rt_event);
    module->module_object[RT_Object_Class_Event].type = RT_Object_Class_Event;
329
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
330

331
#ifdef RT_USING_MAILBOX
332 333 334 335
    /* initialize object container - mailbox */
    rt_list_init(&(module->module_object[RT_Object_Class_MailBox].object_list));
    module->module_object[RT_Object_Class_MailBox].object_size = sizeof(struct rt_mailbox);
    module->module_object[RT_Object_Class_MailBox].type = RT_Object_Class_MailBox;
336
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
337

338
#ifdef RT_USING_MESSAGEQUEUE
339 340 341 342
    /* initialize object container - message queue */
    rt_list_init(&(module->module_object[RT_Object_Class_MessageQueue].object_list));
    module->module_object[RT_Object_Class_MessageQueue].object_size = sizeof(struct rt_messagequeue);
    module->module_object[RT_Object_Class_MessageQueue].type = RT_Object_Class_MessageQueue;
343
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
344

345
#ifdef RT_USING_MEMHEAP
346 347 348 349
    /* initialize object container - memory heap */
    rt_list_init(&(module->module_object[RT_Object_Class_MemHeap].object_list));
    module->module_object[RT_Object_Class_MemHeap].object_size = sizeof(struct rt_memheap);
    module->module_object[RT_Object_Class_MemHeap].type = RT_Object_Class_MemHeap;
350
#endif
351

352
#ifdef RT_USING_MEMPOOL
353 354 355 356
    /* initialize object container - memory pool */
    rt_list_init(&(module->module_object[RT_Object_Class_MemPool].object_list));
    module->module_object[RT_Object_Class_MemPool].object_size = sizeof(struct rt_mempool);
    module->module_object[RT_Object_Class_MemPool].type = RT_Object_Class_MemPool;
357
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
358

359
#ifdef RT_USING_DEVICE
360 361 362 363
    /* initialize object container - device */
    rt_list_init(&(module->module_object[RT_Object_Class_Device].object_list));
    module->module_object[RT_Object_Class_Device].object_size = sizeof(struct rt_device);
    module->module_object[RT_Object_Class_Device].type = RT_Object_Class_Device;
364
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
365

366 367 368 369
    /* initialize object container - timer */
    rt_list_init(&(module->module_object[RT_Object_Class_Timer].object_list));
    module->module_object[RT_Object_Class_Timer].object_size = sizeof(struct rt_timer);
    module->module_object[RT_Object_Class_Timer].type = RT_Object_Class_Timer;
qiuyiuestc's avatar
qiuyiuestc 已提交
370 371
}

qiuyiuestc's avatar
qiuyiuestc 已提交
372 373 374 375 376 377 378
#ifdef RT_USING_HOOK
static void (*rt_module_load_hook)(rt_module_t module);
static void (*rt_module_unload_hook)(rt_module_t module);

/**
 * @addtogroup Hook
 */
D
dzzxzz 已提交
379

D
dogandog 已提交
380
/**@{*/
qiuyiuestc's avatar
qiuyiuestc 已提交
381 382 383 384 385 386 387 388 389

/**
 * This function will set a hook function, which will be invoked when module
 * be loaded to system.
 *
 * @param hook the hook function
 */
void rt_module_load_sethook(void (*hook)(rt_module_t module))
{
390
    rt_module_load_hook = hook;
qiuyiuestc's avatar
qiuyiuestc 已提交
391 392 393 394 395 396 397 398 399 400
}

/**
 * This function will set a hook function, which will be invoked when module
 * be unloaded from system.
 *
 * @param hook the hook function
 */
void rt_module_unload_sethook(void (*hook)(rt_module_t module))
{
401
    rt_module_unload_hook = hook;
qiuyiuestc's avatar
qiuyiuestc 已提交
402 403
}

D
dogandog 已提交
404
/**@}*/
qiuyiuestc's avatar
qiuyiuestc 已提交
405 406
#endif

407 408
static struct rt_module *_load_shared_object(const char *name,
                                             void       *module_ptr)
qiuyiuestc's avatar
qiuyiuestc 已提交
409
{
410
    rt_module_t module = RT_NULL;
411
    rt_bool_t linked   = RT_FALSE;
412
    rt_uint32_t index, module_size = 0;
413 414
    Elf32_Addr vstart_addr, vend_addr;
    rt_bool_t has_vstart;
415 416 417

    RT_ASSERT(module_ptr != RT_NULL);

418
    if (rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) == 0)
419 420 421 422
    {
        /* rtmlinker finished */
        linked = RT_TRUE;
    }
423

424
    /* get the ELF image size */
425 426
    has_vstart = RT_FALSE;
    vstart_addr = vend_addr = RT_NULL;
427 428
    for (index = 0; index < elf_module->e_phnum; index++)
    {
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
        if (phdr[index].p_type != PT_LOAD)
            continue;

        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("LOAD segment: %d, 0x%p, 0x%08x\n",
                                       index, phdr[index].p_vaddr, phdr[index].p_memsz));

        if (phdr[index].p_memsz < phdr[index].p_filesz)
        {
            rt_kprintf("invalid elf: segment %d: p_memsz: %d, p_filesz: %d\n",
                       index, phdr[index].p_memsz, phdr[index].p_filesz);
            return RT_NULL;
        }
        if (!has_vstart)
        {
            vstart_addr = phdr[index].p_vaddr;
            vend_addr = phdr[index].p_vaddr + phdr[index].p_memsz;
            has_vstart = RT_TRUE;
            if (vend_addr < vstart_addr)
            {
                rt_kprintf("invalid elf: segment %d: p_vaddr: %d, p_memsz: %d\n",
                           index, phdr[index].p_vaddr, phdr[index].p_memsz);
                return RT_NULL;
            }
        }
        else
        {
            if (phdr[index].p_vaddr < vend_addr)
            {
                rt_kprintf("invalid elf: segment should be sorted and not overlapped\n");
                return RT_NULL;
            }
            if (phdr[index].p_vaddr > vend_addr + 16)
            {
                /* There should not be too much padding in the object files. */
                rt_kprintf("warning: too much padding before segment %d\n", index);
            }

            vend_addr = phdr[index].p_vaddr + phdr[index].p_memsz;
            if (vend_addr < phdr[index].p_vaddr)
            {
                rt_kprintf("invalid elf: "
                           "segment %d address overflow\n", index);
                return RT_NULL;
            }
        }
474 475
    }

476 477 478 479 480
    module_size = vend_addr - vstart_addr;

    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("module size: %d, vstart_addr: 0x%p\n",
                                   module_size, vstart_addr));

481 482
    if (module_size == 0)
    {
483
        rt_kprintf("Module: size error\n");
484

485
        return RT_NULL;
486
    }
487 488

    /* allocate module */
489 490 491 492
    module = (struct rt_module *)rt_object_allocate(RT_Object_Class_Module,
                                                    name);
    if (!module)
        return RT_NULL;
493

494 495
    module->vstart_addr = vstart_addr;

496
    module->nref = 0;
497

498 499 500 501
    /* allocate module space */
    module->module_space = rt_malloc(module_size);
    if (module->module_space == RT_NULL)
    {
502
        rt_kprintf("Module: allocate space failed.\n");
503 504 505 506 507 508
        rt_object_delete(&(module->parent));

        return RT_NULL;
    }

    /* zero all space */
509
    rt_memset(module->module_space, 0, module_size);
510 511 512 513 514

    for (index = 0; index < elf_module->e_phnum; index++)
    {
        if (phdr[index].p_type == PT_LOAD)
        {
515
            rt_memcpy(module->module_space + phdr[index].p_vaddr - vstart_addr,
516 517
                      (rt_uint8_t *)elf_module + phdr[index].p_offset,
                      phdr[index].p_filesz);
518 519
        }
    }
520 521

    /* set module entry */
522
    module->module_entry = module->module_space
523
                           + elf_module->e_entry - vstart_addr;
524

525 526 527 528 529 530 531 532
    /* handle relocation section */
    for (index = 0; index < elf_module->e_shnum; index ++)
    {
        rt_uint32_t i, nr_reloc;
        Elf32_Sym *symtab;
        Elf32_Rel *rel;
        rt_uint8_t *strtab;
        static rt_bool_t unsolved = RT_FALSE;
533

534 535
        if (!IS_REL(shdr[index]))
            continue;
536 537 538 539 540

        /* get relocate item */
        rel = (Elf32_Rel *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset);

        /* locate .rel.plt and .rel.dyn section */
541 542 543
        symtab = (Elf32_Sym *)((rt_uint8_t *)module_ptr +
                               shdr[shdr[index].sh_link].sh_offset);
        strtab = (rt_uint8_t *)module_ptr +
544
                 shdr[shdr[shdr[index].sh_link].sh_link].sh_offset;
545
        nr_reloc = (rt_uint32_t)(shdr[index].sh_size / sizeof(Elf32_Rel));
546 547 548 549 550 551

        /* relocate every items */
        for (i = 0; i < nr_reloc; i ++)
        {
            Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)];

552 553 554
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("relocate symbol %s shndx %d\n",
                                           strtab + sym->st_name,
                                           sym->st_shndx));
555

556
            if ((sym->st_shndx != SHT_NULL) ||
557 558 559 560
                (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
#ifdef MODULE_USING_386
                || ( (ELF_ST_BIND(sym->st_info) == STB_GLOBAL) && (ELF_ST_TYPE(sym->st_info) == STT_OBJECT) )
#endif
561
               )
562
            {
563
                rt_module_arm_relocate(module, rel,
564 565 566
                                       (Elf32_Addr)(module->module_space
                                                    + sym->st_value
                                                    - vstart_addr));
567
            }
568
            else if (!linked)
569 570 571
            {
                Elf32_Addr addr;

572 573
                RT_DEBUG_LOG(RT_DEBUG_MODULE, ("relocate symbol: %s\n",
                                               strtab + sym->st_name));
574 575 576 577 578

                /* need to resolve symbol in kernel symbol table */
                addr = rt_module_symbol_find((const char *)(strtab + sym->st_name));
                if (addr == 0)
                {
579
                    rt_kprintf("Module: can't find %s in kernel symbol table\n",
580
                               strtab + sym->st_name);
581
                    unsolved = RT_TRUE;
582
                }
583 584 585 586 587 588 589 590 591 592 593
                else
                    rt_module_arm_relocate(module, rel, addr);
            }
            rel ++;
        }

        if (unsolved)
        {
            rt_object_delete(&(module->parent));

            return RT_NULL;
594
        }
595 596 597 598
    }

    /* construct module symbol table */
    for (index = 0; index < elf_module->e_shnum; index ++)
599
    {
600
        /* find .dynsym section */
601
        rt_uint8_t *shstrab;
602
        shstrab = (rt_uint8_t *)module_ptr +
603
                  shdr[elf_module->e_shstrndx].sh_offset;
604 605 606 607 608 609 610 611
        if (rt_strcmp((const char *)(shstrab + shdr[index].sh_name), ELF_DYNSYM) == 0)
            break;
    }

    /* found .dynsym section */
    if (index != elf_module->e_shnum)
    {
        int i, count = 0;
612
        Elf32_Sym  *symtab = RT_NULL;
613 614
        rt_uint8_t *strtab = RT_NULL;

615
        symtab = (Elf32_Sym *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset);
616 617
        strtab = (rt_uint8_t *)module_ptr + shdr[shdr[index].sh_link].sh_offset;

618
        for (i = 0; i < shdr[index].sh_size / sizeof(Elf32_Sym); i++)
619
        {
620
            if ((ELF_ST_BIND(symtab[i].st_info) == STB_GLOBAL) &&
621 622 623 624 625
                (ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC))
                count ++;
        }

        module->symtab = (struct rt_module_symtab *)rt_malloc
626
                         (count * sizeof(struct rt_module_symtab));
627
        module->nsym = count;
628
        for (i = 0, count = 0; i < shdr[index].sh_size / sizeof(Elf32_Sym); i++)
629 630
        {
            rt_size_t length;
631 632

            if ((ELF_ST_BIND(symtab[i].st_info) != STB_GLOBAL) ||
633 634
                (ELF_ST_TYPE(symtab[i].st_info) != STT_FUNC))
                continue;
635 636 637

            length = rt_strlen((const char *)(strtab + symtab[i].st_name)) + 1;

638
            module->symtab[count].addr =
639 640 641
                (void *)(module->module_space + symtab[i].st_value);
            module->symtab[count].name = rt_malloc(length);
            rt_memset((void *)module->symtab[count].name, 0, length);
642
            rt_memcpy((void *)module->symtab[count].name,
643 644
                      strtab + symtab[i].st_name,
                      length);
645
            count ++;
646
        }
647 648 649
    }

    return module;
650 651
}

652 653
static struct rt_module* _load_relocated_object(const char *name,
                                                void       *module_ptr)
654
{
655 656 657 658 659 660
    rt_uint32_t index, rodata_addr = 0, bss_addr = 0, data_addr = 0;
    rt_uint32_t module_addr = 0, module_size = 0;
    struct rt_module *module = RT_NULL;
    rt_uint8_t *ptr, *strtab, *shstrab;

    /* get the ELF image size */
661
    for (index = 0; index < elf_module->e_shnum; index ++)
662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
    {
        /* text */
        if (IS_PROG(shdr[index]) && IS_AX(shdr[index]))
        {
            module_size += shdr[index].sh_size;
            module_addr = shdr[index].sh_addr;
        }
        /* rodata */
        if (IS_PROG(shdr[index]) && IS_ALLOC(shdr[index]))
        {
            module_size += shdr[index].sh_size;
        }
        /* data */
        if (IS_PROG(shdr[index]) && IS_AW(shdr[index]))
        {
            module_size += shdr[index].sh_size;
        }
        /* bss */
        if (IS_NOPROG(shdr[index]) && IS_AW(shdr[index]))
        {
            module_size += shdr[index].sh_size;
        }
    }

    /* no text, data and bss on image */
    if (module_size == 0)
        return RT_NULL;

    /* allocate module */
691
    module = (struct rt_module *)
692
             rt_object_allocate(RT_Object_Class_Module, (const char *)name);
693 694 695
    if (module == RT_NULL)
        return RT_NULL;

696 697
    module->vstart_addr = 0;

698 699 700 701
    /* allocate module space */
    module->module_space = rt_malloc(module_size);
    if (module->module_space == RT_NULL)
    {
702
        rt_kprintf("Module: allocate space failed.\n");
703 704 705 706 707 708 709 710 711 712
        rt_object_delete(&(module->parent));

        return RT_NULL;
    }

    /* zero all space */
    ptr = module->module_space;
    rt_memset(ptr, 0, module_size);

    /* load text and data section */
713
    for (index = 0; index < elf_module->e_shnum; index ++)
714 715 716 717
    {
        /* load text section */
        if (IS_PROG(shdr[index]) && IS_AX(shdr[index]))
        {
718 719 720
            rt_memcpy(ptr,
                      (rt_uint8_t *)elf_module + shdr[index].sh_offset,
                      shdr[index].sh_size);
721 722
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("load text 0x%x, size %d\n",
                                           ptr, shdr[index].sh_size));
723 724 725 726 727 728
            ptr += shdr[index].sh_size;
        }

        /* load rodata section */
        if (IS_PROG(shdr[index]) && IS_ALLOC(shdr[index]))
        {
729 730 731
            rt_memcpy(ptr,
                      (rt_uint8_t *)elf_module + shdr[index].sh_offset,
                      shdr[index].sh_size);
732
            rodata_addr = (rt_uint32_t)ptr;
733 734 735
            RT_DEBUG_LOG(RT_DEBUG_MODULE,
                         ("load rodata 0x%x, size %d, rodata 0x%x\n",
                          ptr, shdr[index].sh_size, *(rt_uint32_t *)data_addr));
736 737 738 739 740 741
            ptr += shdr[index].sh_size;
        }

        /* load data section */
        if (IS_PROG(shdr[index]) && IS_AW(shdr[index]))
        {
742 743 744
            rt_memcpy(ptr,
                      (rt_uint8_t *)elf_module + shdr[index].sh_offset,
                      shdr[index].sh_size);
745
            data_addr = (rt_uint32_t)ptr;
746 747 748
            RT_DEBUG_LOG(RT_DEBUG_MODULE,
                         ("load data 0x%x, size %d, data 0x%x\n",
                          ptr, shdr[index].sh_size, *(rt_uint32_t *)data_addr));
749 750 751 752 753 754 755 756
            ptr += shdr[index].sh_size;
        }

        /* load bss section */
        if (IS_NOPROG(shdr[index]) && IS_AW(shdr[index]))
        {
            rt_memset(ptr, 0, shdr[index].sh_size);
            bss_addr = (rt_uint32_t)ptr;
757 758
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("load bss 0x%x, size %d,\n",
                                           ptr, shdr[index].sh_size));
759 760 761 762
        }
    }

    /* set module entry */
763 764
    module->module_entry =
        (rt_uint8_t *)module->module_space + elf_module->e_entry - module_addr;
765 766 767 768 769 770 771

    /* handle relocation section */
    for (index = 0; index < elf_module->e_shnum; index ++)
    {
        rt_uint32_t i, nr_reloc;
        Elf32_Sym *symtab;
        Elf32_Rel *rel;
772

773 774
        if (!IS_REL(shdr[index]))
            continue;
775

776
        /* get relocate item */
777
        rel = (Elf32_Rel *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset);
778 779

        /* locate .dynsym and .dynstr */
780
        symtab   = (Elf32_Sym *)((rt_uint8_t *)module_ptr +
781
                                 shdr[shdr[index].sh_link].sh_offset);
782
        strtab   = (rt_uint8_t *)module_ptr +
783
                   shdr[shdr[shdr[index].sh_link].sh_link].sh_offset;
784
        shstrab  = (rt_uint8_t *)module_ptr +
785
                   shdr[elf_module->e_shstrndx].sh_offset;
786
        nr_reloc = (rt_uint32_t)(shdr[index].sh_size / sizeof(Elf32_Rel));
787 788 789 790 791

        /* relocate every items */
        for (i = 0; i < nr_reloc; i ++)
        {
            Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)];
792

793 794
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("relocate symbol: %s\n",
                                           strtab + sym->st_name));
795 796 797

            if (sym->st_shndx != STN_UNDEF)
            {
798 799
                if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) ||
                    (ELF_ST_TYPE(sym->st_info) == STT_OBJECT))
800
                {
801
                    if (rt_strncmp((const char *)(shstrab +
802
                                                  shdr[sym->st_shndx].sh_name), ELF_RODATA, 8) == 0)
803 804
                    {
                        /* relocate rodata section */
805
                        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rodata\n"));
806
                        rt_module_arm_relocate(module, rel,
807
                                               (Elf32_Addr)(rodata_addr + sym->st_value));
808
                    }
809
                    else if (rt_strncmp((const char *)
810
                                        (shstrab + shdr[sym->st_shndx].sh_name), ELF_BSS, 5) == 0)
811 812
                    {
                        /* relocate bss section */
813
                        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("bss\n"));
814
                        rt_module_arm_relocate(module, rel,
815
                                               (Elf32_Addr)bss_addr + sym->st_value);
816
                    }
817
                    else if (rt_strncmp((const char *)(shstrab + shdr[sym->st_shndx].sh_name),
818
                                        ELF_DATA, 6) == 0)
819 820
                    {
                        /* relocate data section */
821
                        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("data\n"));
822
                        rt_module_arm_relocate(module, rel,
823
                                               (Elf32_Addr)data_addr + sym->st_value);
824 825
                    }
                }
826 827 828 829 830 831 832 833 834
                else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC)
                {
                    /* relocate function */
                    rt_module_arm_relocate(module, rel,
                                           (Elf32_Addr)((rt_uint8_t *)
                                                        module->module_space
                                                        - module_addr
                                                        + sym->st_value));
                }
835
            }
836
            else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC)
837 838
            {
                /* relocate function */
839 840 841 842 843
                rt_module_arm_relocate(module, rel,
                                       (Elf32_Addr)((rt_uint8_t *)
                                                    module->module_space
                                                    - module_addr
                                                    + sym->st_value));
844 845 846 847 848
            }
            else
            {
                Elf32_Addr addr;

849
                if (ELF32_R_TYPE(rel->r_info) != R_ARM_V4BX)
850
                {
851 852
                    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("relocate symbol: %s\n",
                                                   strtab + sym->st_name));
853

854
                    /* need to resolve symbol in kernel symbol table */
855
                    addr = rt_module_symbol_find((const char *)(strtab + sym->st_name));
856 857 858
                    if (addr != (Elf32_Addr)RT_NULL)
                    {
                        rt_module_arm_relocate(module, rel, addr);
859 860
                        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("symbol addr 0x%x\n",
                                                       addr));
861 862
                    }
                    else
863
                        rt_kprintf("Module: can't find %s in kernel symbol table\n",
864
                                   strtab + sym->st_name);
865 866 867
                }
                else
                {
868
                    rt_module_arm_relocate(module, rel,
869
                                           (Elf32_Addr)((rt_uint8_t *)
870 871 872
                                                        module->module_space
                                                        - module_addr
                                                        + sym->st_value));
873 874 875 876 877 878 879
                }
            }
            rel ++;
        }
    }

    return module;
880 881
}

882
#define RT_MODULE_ARG_MAX    8
883
static int _rt_module_split_arg(char *cmd, rt_size_t length, char *argv[])
884 885 886 887 888 889 890
{
    int argc = 0;
    char *ptr = cmd;

    while ((ptr - cmd) < length)
    {
        /* strip bank and tab */
891
        while ((*ptr == ' ' || *ptr == '\t') && (ptr - cmd) < length)
892 893
            *ptr++ = '\0';
        /* check whether it's the end of line */
894
        if ((ptr - cmd) >= length) break;
895 896 897 898 899 900 901

        /* handle string with quote */
        if (*ptr == '"')
        {
            argv[argc++] = ++ptr;

            /* skip this string */
902
            while (*ptr != '"' && (ptr - cmd) < length)
903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
                if (*ptr ++ == '\\')  ptr ++;
            if ((ptr - cmd) >= length) break;

            /* skip '"' */
            *ptr ++ = '\0';
        }
        else
        {
            argv[argc++] = ptr;
            while ((*ptr != ' ' && *ptr != '\t') && (ptr - cmd) < length)
                ptr ++;
        }

        if (argc >= RT_MODULE_ARG_MAX) break;
    }

    return argc;
}

/* module main thread entry */
923
static void module_main_entry(void *parameter)
924 925 926
{
    int argc;
    char *argv[RT_MODULE_ARG_MAX];
927
    typedef int (*main_func_t)(int argc, char **argv);
928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948

    rt_module_t module = (rt_module_t) parameter;
    if (module == RT_NULL)
        return;

    if (module->module_cmd_line == RT_NULL && module->module_cmd_size != 0)
        /* malloc for module_cmd_line failed. */
        return;

    /* FIXME: we should run some C++ initialize code before jump into the
     * entry. */

    if (module->module_cmd_line == RT_NULL)
    {
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("run bare entry: 0x%p\n",
                                       module->module_entry));
        ((main_func_t)module->module_entry)(0, RT_NULL);
        return;
    }

    rt_memset(argv, 0x00, sizeof(argv));
949
    argc = _rt_module_split_arg((char *)module->module_cmd_line,
950 951 952 953 954 955 956 957 958 959 960 961
                                module->module_cmd_size, argv);
    if (argc == 0)
        return;

    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("run main entry: 0x%p with %s\n",
                                   module->module_entry,
                                   module->module_cmd_line));
    /* do the main function */
    ((main_func_t)module->module_entry)(argc, argv);
    return;
}

962
/**
963
 * This function will load a module with a main function from memory and create a
964
 * main thread for it
965 966 967
 *
 * @param name the name of module, which shall be unique
 * @param module_ptr the memory address of module image
968
 * @argc the count of argument
969
 * @argd the argument data, which should be a
970 971 972
 *
 * @return the module object
 */
973 974
rt_module_t rt_module_do_main(const char *name,
                              void *module_ptr,
975
                              const char *cmd_line,
976
                              int line_size)
977
{
978 979 980 981
    rt_module_t module;

    RT_DEBUG_NOT_IN_INTERRUPT;

982
    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_load: %s\n", name));
983 984

    /* check ELF header */
985 986
    if (rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) != 0 &&
        rt_memcmp(elf_module->e_ident, ELFMAG, SELFMAG) != 0)
987
    {
988
        rt_kprintf("Module: magic error\n");
989 990 991 992 993

        return RT_NULL;
    }

    /* check ELF class */
994
    if (elf_module->e_ident[EI_CLASS] != ELFCLASS32)
995
    {
996
        rt_kprintf("Module: ELF class error\n");
997 998 999 1000

        return RT_NULL;
    }

1001
    if (elf_module->e_type == ET_REL)
1002 1003 1004
    {
        module = _load_relocated_object(name, module_ptr);
    }
1005
    else if (elf_module->e_type == ET_DYN)
1006 1007 1008 1009 1010
    {
        module = _load_shared_object(name, module_ptr);
    }
    else
    {
1011
        rt_kprintf("Module: unsupported elf type\n");
1012 1013 1014 1015

        return RT_NULL;
    }

1016
    if (module == RT_NULL)
1017 1018 1019 1020
        return RT_NULL;

    /* init module object container */
    rt_module_init_object_container(module);
1021

1022 1023 1024
    if (line_size && cmd_line)
    {
        /* set module argument */
1025
        module->module_cmd_line = (rt_uint8_t *)rt_malloc(line_size + 1);
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
        if (module->module_cmd_line)
        {
            rt_memcpy(module->module_cmd_line, cmd_line, line_size);
            module->module_cmd_line[line_size] = '\0';
        }
        module->module_cmd_size = line_size;
    }
    else
    {
        /* initialize an empty command */
        module->module_cmd_line = RT_NULL;
        module->module_cmd_size = 0;
    }

1040 1041 1042 1043
    /* increase module reference count */
    module->nref ++;

    if (elf_module->e_entry != 0)
1044
    {
qiuyiuestc's avatar
qiuyiuestc 已提交
1045
#ifdef RT_USING_SLAB
1046 1047
        /* init module memory allocator */
        module->mem_list = RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
1048

1049
        /* create page array */
B
Bernard Xiong 已提交
1050
        module->page_array =
1051
            (void *)rt_malloc(PAGE_COUNT_MAX * sizeof(struct rt_page_info));
1052
        module->page_cnt = 0;
1053 1054
#endif

1055
        /* create module thread */
1056
        module->module_thread = rt_thread_create(name,
1057 1058 1059
                                                 module_main_entry, module,
                                                 RT_USING_MODULE_STKSZ,
                                                 RT_USING_MODULE_PRIO, 10);
1060

1061 1062
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("thread entry 0x%x\n",
                                       module->module_entry));
1063 1064 1065

        /* set module id */
        module->module_thread->module_id = (void *)module;
1066 1067 1068 1069
        module->parent.flag = RT_MODULE_FLAG_WITHENTRY;

        /* startup module thread */
        rt_thread_startup(module->module_thread);
1070
    }
1071 1072 1073 1074
    else
    {
        /* without entry point */
        module->parent.flag |= RT_MODULE_FLAG_WITHOUTENTRY;
1075
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1076

qiuyiuestc's avatar
qiuyiuestc 已提交
1077
#ifdef RT_USING_HOOK
1078 1079 1080 1081
    if (rt_module_load_hook != RT_NULL)
    {
        rt_module_load_hook(module);
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1082 1083
#endif

1084
    return module;
1085 1086
}

1087
/**
1088
 * This function will load a module from memory and create a thread for it
1089 1090 1091 1092 1093 1094
 *
 * @param name the name of module, which shall be unique
 * @param module_ptr the memory address of module image
 *
 * @return the module object
 */
1095
rt_module_t rt_module_load(const char *name, void *module_ptr)
1096
{
1097
    return rt_module_do_main(name, module_ptr, RT_NULL, 0);
1098 1099
}

1100 1101
#ifdef RT_USING_DFS
#include <dfs_posix.h>
qiuyiuestc's avatar
qiuyiuestc 已提交
1102

1103
static char *_module_name(const char *path)
qiuyiuestc's avatar
qiuyiuestc 已提交
1104
{
1105
    const char *first, *end, *ptr;
1106
    char *name;
qiuyiuestc's avatar
qiuyiuestc 已提交
1107
    int size;
1108

1109 1110 1111 1112 1113
    ptr   = (char *)path;
    first = ptr;
    end   = path + rt_strlen(path);

    while (*ptr != '\0')
qiuyiuestc's avatar
qiuyiuestc 已提交
1114
    {
1115 1116 1117 1118
        if (*ptr == '/')
            first = ptr + 1;
        if (*ptr == '.')
            end = ptr - 1;
1119

1120
        ptr ++;
qiuyiuestc's avatar
qiuyiuestc 已提交
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
    }

    size = end - first + 1;
    name = rt_malloc(size);
    rt_strncpy(name, first, size);
    name[size] = '\0';

    return name;
}

qiuyiuestc's avatar
qiuyiuestc 已提交
1131
/**
B
bernard.xiong@gmail.com 已提交
1132
 * This function will load a module from a file
qiuyiuestc's avatar
qiuyiuestc 已提交
1133
 *
B
bernard.xiong@gmail.com 已提交
1134
 * @param path the full path of application module
qiuyiuestc's avatar
qiuyiuestc 已提交
1135 1136 1137
 *
 * @return the module object
 */
D
dzzxzz 已提交
1138
rt_module_t rt_module_open(const char *path)
qiuyiuestc's avatar
qiuyiuestc 已提交
1139
{
1140 1141 1142 1143
    int fd, length;
    struct rt_module *module;
    struct stat s;
    char *buffer, *offset_ptr;
1144
    char *name;
1145 1146 1147 1148 1149 1150

    RT_DEBUG_NOT_IN_INTERRUPT;

    /* check parameters */
    RT_ASSERT(path != RT_NULL);

1151
    if (stat(path, &s) != 0)
1152
    {
1153
        rt_kprintf("Module: access %s failed\n", path);
1154 1155 1156 1157 1158 1159

        return RT_NULL;
    }
    buffer = (char *)rt_malloc(s.st_size);
    if (buffer == RT_NULL)
    {
1160
        rt_kprintf("Module: out of memory\n");
1161 1162 1163 1164 1165 1166 1167 1168

        return RT_NULL;
    }

    offset_ptr = buffer;
    fd = open(path, O_RDONLY, 0);
    if (fd < 0)
    {
1169
        rt_kprintf("Module: open %s failed\n", path);
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188
        rt_free(buffer);

        return RT_NULL;
    }

    do
    {
        length = read(fd, offset_ptr, 4096);
        if (length > 0)
        {
            offset_ptr += length;
        }
    }while (length > 0);

    /* close fd */
    close(fd);

    if ((rt_uint32_t)offset_ptr - (rt_uint32_t)buffer != s.st_size)
    {
1189
        rt_kprintf("Module: read file failed\n");
1190 1191 1192 1193 1194
        rt_free(buffer);

        return RT_NULL;
    }

1195 1196
    name   = _module_name(path);
    module = rt_module_load(name, (void *)buffer);
1197
    rt_free(buffer);
qiuyiuestc's avatar
qiuyiuestc 已提交
1198
    rt_free(name);
1199 1200

    return module;
qiuyiuestc's avatar
qiuyiuestc 已提交
1201
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1202

1203 1204 1205 1206
/**
 * This function will do a excutable program with main function and parameters.
 *
 * @param path the full path of application module
1207 1208
 * @param cmd_line the command line of program
 * @param size the size of command line of program
1209 1210 1211
 *
 * @return the module object
 */
1212
rt_module_t rt_module_exec_cmd(const char *path, const char *cmd_line, int size)
1213 1214 1215 1216 1217 1218
{
    struct stat s;
    int fd, length;
    char *name, *buffer, *offset_ptr;
    struct rt_module *module = RT_NULL;

1219
    name = buffer = RT_NULL;
1220 1221 1222 1223 1224 1225

    RT_DEBUG_NOT_IN_INTERRUPT;

    /* check parameters */
    RT_ASSERT(path != RT_NULL);

1226
    /* get file size */
1227
    if (stat(path, &s) != 0)
1228 1229 1230 1231 1232
    {
        rt_kprintf("Module: access %s failed\n", path);
        goto __exit;
    }

1233
    /* allocate buffer to save program */
1234 1235 1236 1237
    offset_ptr = buffer = (char *)rt_malloc(s.st_size);
    if (buffer == RT_NULL)
    {
        rt_kprintf("Module: out of memory\n");
1238
        goto __exit;
1239 1240 1241 1242 1243 1244
    }

    fd = open(path, O_RDONLY, 0);
    if (fd < 0)
    {
        rt_kprintf("Module: open %s failed\n", path);
1245
        goto __exit;
1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261
    }

    do
    {
        length = read(fd, offset_ptr, 4096);
        if (length > 0)
        {
            offset_ptr += length;
        }
    }while (length > 0);
    /* close fd */
    close(fd);

    if ((rt_uint32_t)offset_ptr - (rt_uint32_t)buffer != s.st_size)
    {
        rt_kprintf("Module: read file failed\n");
1262
        goto __exit;
1263 1264
    }

1265
    /* get module */
1266
    name   = _module_name(path);
1267
    /* execute module */
1268 1269 1270 1271 1272 1273 1274 1275 1276
    module = rt_module_do_main(name, (void *)buffer, cmd_line, size);

__exit:
    rt_free(buffer);
    rt_free(name);

    return module;
}

qiuyiuestc's avatar
qiuyiuestc 已提交
1277 1278
#if defined(RT_USING_FINSH)
#include <finsh.h>
1279
FINSH_FUNCTION_EXPORT_ALIAS(rt_module_open, exec, exec module from a file);
qiuyiuestc's avatar
qiuyiuestc 已提交
1280
#endif
1281

qiuyiuestc's avatar
qiuyiuestc 已提交
1282 1283
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
1284
/**
1285
 * This function will destroy a module and release its resource.
qiuyiuestc's avatar
qiuyiuestc 已提交
1286
 *
1287
 * @param module the module to be destroyed.
qiuyiuestc's avatar
qiuyiuestc 已提交
1288 1289 1290
 *
 * @return the operation status, RT_EOK on OK; -RT_ERROR on error
 */
1291
rt_err_t rt_module_destroy(rt_module_t module)
qiuyiuestc's avatar
qiuyiuestc 已提交
1292
{
1293 1294 1295 1296 1297 1298 1299 1300
    int i;
    struct rt_object *object;
    struct rt_list_node *list;

    RT_DEBUG_NOT_IN_INTERRUPT;

    /* check parameter */
    RT_ASSERT(module != RT_NULL);
1301
    RT_ASSERT(module->nref == 0);
1302

1303 1304
    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_destroy: %8.*s\n",
                                   RT_NAME_MAX, module->parent.name));
1305 1306 1307 1308

    /* module has entry point */
    if (!(module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY))
    {
qiuyiuestc's avatar
qiuyiuestc 已提交
1309
#ifdef RT_USING_SEMAPHORE
1310
        /* delete semaphores */
1311
        list = &module->module_object[RT_Object_Class_Semaphore].object_list;
1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_sem_detach((rt_sem_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_sem_delete((rt_sem_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1326 1327 1328
#endif

#ifdef RT_USING_MUTEX
1329
        /* delete mutexs*/
1330
        list = &module->module_object[RT_Object_Class_Mutex].object_list;
1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_mutex_detach((rt_mutex_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_mutex_delete((rt_mutex_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1345 1346 1347
#endif

#ifdef RT_USING_EVENT
1348
        /* delete mailboxs */
1349
        list = &module->module_object[RT_Object_Class_Event].object_list;
1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_event_detach((rt_event_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_event_delete((rt_event_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1364 1365 1366
#endif

#ifdef RT_USING_MAILBOX
1367
        /* delete mailboxs */
1368
        list = &module->module_object[RT_Object_Class_MailBox].object_list;
1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_mb_detach((rt_mailbox_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_mb_delete((rt_mailbox_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1383 1384 1385
#endif

#ifdef RT_USING_MESSAGEQUEUE
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401
        /* delete msgqueues */
        list = &module->module_object[RT_Object_Class_MessageQueue].object_list;
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_mq_detach((rt_mq_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_mq_delete((rt_mq_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1402 1403 1404
#endif

#ifdef RT_USING_MEMPOOL
1405
        /* delete mempools */
1406
        list = &module->module_object[RT_Object_Class_MemPool].object_list;
1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_mp_detach((rt_mp_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_mp_delete((rt_mp_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1421 1422 1423
#endif

#ifdef RT_USING_DEVICE
1424
        /* delete devices */
1425
        list = &module->module_object[RT_Object_Class_Device].object_list;
1426 1427 1428 1429 1430
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            rt_device_unregister((rt_device_t)object);
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1431 1432
#endif

1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448
        /* delete timers */
        list = &module->module_object[RT_Object_Class_Timer].object_list;
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_timer_detach((rt_timer_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_timer_delete((rt_timer_t)object);
            }
        }
1449 1450 1451 1452 1453 1454

        /* delete command line */
        if (module->module_cmd_line != RT_NULL)
        {
            rt_free(module->module_cmd_line);
        }
1455
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1456

1457
#ifdef RT_USING_SLAB
1458 1459 1460
    if (module->page_cnt > 0)
    {
        struct rt_page_info *page = (struct rt_page_info *)module->page_array;
B
bernard.xiong@gmail.com 已提交
1461

1462
        rt_kprintf("Module: warning - memory still hasn't been free finished\n");
qiuyiuestc's avatar
qiuyiuestc 已提交
1463

1464
        while (module->page_cnt != 0)
1465 1466 1467 1468
        {
            rt_module_free_page(module, page[0].page_ptr, page[0].npage);
        }
    }
1469
#endif
D
dzzxzz 已提交
1470

1471 1472
    /* release module space memory */
    rt_free(module->module_space);
qiuyiuestc's avatar
qiuyiuestc 已提交
1473

1474
    /* release module symbol table */
1475
    for (i = 0; i < module->nsym; i ++)
1476
    {
1477
        rt_free((void *)module->symtab[i].name);
1478
    }
1479 1480
    if (module->symtab != RT_NULL)
        rt_free(module->symtab);
qiuyiuestc's avatar
qiuyiuestc 已提交
1481

qiuyiuestc's avatar
qiuyiuestc 已提交
1482
#ifdef RT_USING_SLAB
1483
    if (module->page_array != RT_NULL)
1484
        rt_free(module->page_array);
qiuyiuestc's avatar
qiuyiuestc 已提交
1485
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
1486

1487 1488
    /* delete module object */
    rt_object_delete((rt_object_t)module);
qiuyiuestc's avatar
qiuyiuestc 已提交
1489

1490
    return RT_EOK;
qiuyiuestc's avatar
qiuyiuestc 已提交
1491 1492
}

1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507
/**
 * This function will unload a module from memory and release resources
 *
 * @param module the module to be unloaded
 *
 * @return the operation status, RT_EOK on OK; -RT_ERROR on error
 */
rt_err_t rt_module_unload(rt_module_t module)
{
    struct rt_object *object;
    struct rt_list_node *list;

    RT_DEBUG_NOT_IN_INTERRUPT;

    /* check parameter */
1508 1509
    if (module == RT_NULL)
        return -RT_ERROR;
1510

1511
    rt_enter_critical();
1512 1513
    if (!(module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY))
    {
1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535
        /* delete all sub-threads */
        list = &module->module_object[RT_Object_Class_Thread].object_list;
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_thread_detach((rt_thread_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_thread_delete((rt_thread_t)object);
            }
        }

        /* delete the main thread of module */
        if (module->module_thread != RT_NULL)
        {
            rt_thread_delete(module->module_thread);
        }
1536
    }
1537
    rt_exit_critical();
1538 1539

#ifdef RT_USING_HOOK
1540 1541 1542 1543
    if (rt_module_unload_hook != RT_NULL)
    {
        rt_module_unload_hook(module);
    }
1544 1545
#endif

1546
    return RT_EOK;
1547 1548
}

qiuyiuestc's avatar
qiuyiuestc 已提交
1549 1550 1551 1552 1553 1554 1555
/**
 * This function will find the specified module.
 *
 * @param name the name of module finding
 *
 * @return the module
 */
D
dzzxzz 已提交
1556
rt_module_t rt_module_find(const char *name)
qiuyiuestc's avatar
qiuyiuestc 已提交
1557
{
1558 1559 1560
    struct rt_object_information *information;
    struct rt_object *object;
    struct rt_list_node *node;
qiuyiuestc's avatar
qiuyiuestc 已提交
1561

1562
    RT_DEBUG_NOT_IN_INTERRUPT;
1563

1564 1565
    /* enter critical */
    rt_enter_critical();
B
bernard.xiong 已提交
1566

1567
    /* try to find device object */
1568 1569
    information = rt_object_get_information(RT_Object_Class_Module);
    RT_ASSERT(information != RT_NULL);
1570
    for (node = information->object_list.next;
1571 1572
         node != &(information->object_list);
         node = node->next)
1573 1574 1575 1576 1577 1578
    {
        object = rt_list_entry(node, struct rt_object, list);
        if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
        {
            /* leave critical */
            rt_exit_critical();
B
bernard.xiong 已提交
1579

1580 1581 1582
            return (rt_module_t)object;
        }
    }
B
bernard.xiong 已提交
1583

1584 1585
    /* leave critical */
    rt_exit_critical();
B
bernard.xiong 已提交
1586

1587 1588
    /* not found */
    return RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
1589
}
1590
RTM_EXPORT(rt_module_find);
qiuyiuestc's avatar
qiuyiuestc 已提交
1591

qiuyiuestc's avatar
qiuyiuestc 已提交
1592 1593 1594 1595 1596 1597 1598 1599 1600
#ifdef RT_USING_SLAB
/*
 * This function will allocate the numbers page with specified size
 * in page memory.
 *
 * @param size the size of memory to be allocated.
 * @note this function is used for RT-Thread Application Module
 */
static void *rt_module_malloc_page(rt_size_t npages)
qiuyiuestc's avatar
qiuyiuestc 已提交
1601
{
1602 1603
    void *chunk;
    struct rt_page_info *page;
1604
    rt_module_t self_module;
1605

1606 1607
    self_module = rt_module_self();
    RT_ASSERT(self_module != RT_NULL);
qiuyiuestc's avatar
qiuyiuestc 已提交
1608

1609 1610 1611
    chunk = rt_page_alloc(npages);
    if (chunk == RT_NULL)
        return RT_NULL;
1612

1613 1614
    page = (struct rt_page_info *)self_module->page_array;
    page[self_module->page_cnt].page_ptr = chunk;
1615
    page[self_module->page_cnt].npage    = npages;
1616
    self_module->page_cnt ++;
qiuyiuestc's avatar
qiuyiuestc 已提交
1617

1618
    RT_ASSERT(self_module->page_cnt <= PAGE_COUNT_MAX);
1619 1620
    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_malloc_page 0x%x %d\n",
                                   chunk, npages));
D
dzzxzz 已提交
1621

1622
    return chunk;
qiuyiuestc's avatar
qiuyiuestc 已提交
1623
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1624

qiuyiuestc's avatar
qiuyiuestc 已提交
1625
/*
D
dzzxzz 已提交
1626
 * This function will release the previously allocated memory page
qiuyiuestc's avatar
qiuyiuestc 已提交
1627 1628 1629 1630
 * by rt_malloc_page.
 *
 * @param page_ptr the page address to be released.
 * @param npages the number of page shall be released.
B
bernard.xiong@gmail.com 已提交
1631
 *
qiuyiuestc's avatar
qiuyiuestc 已提交
1632 1633
 * @note this function is used for RT-Thread Application Module
 */
1634 1635 1636
static void rt_module_free_page(rt_module_t module,
                                void       *page_ptr,
                                rt_size_t   npages)
qiuyiuestc's avatar
qiuyiuestc 已提交
1637
{
1638 1639
    int i, index;
    struct rt_page_info *page;
1640
    rt_module_t self_module;
1641

1642 1643
    self_module = rt_module_self();
    RT_ASSERT(self_module != RT_NULL);
1644

1645 1646
    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_free_page 0x%x %d\n",
                                   page_ptr, npages));
1647 1648
    rt_page_free(page_ptr, npages);

1649
    page = (struct rt_page_info *)module->page_array;
1650

1651
    for (i = 0; i < module->page_cnt; i ++)
1652 1653 1654 1655 1656
    {
        if (page[i].page_ptr == page_ptr)
        {
            if (page[i].npage == npages + 1)
            {
1657 1658 1659
                page[i].page_ptr +=
                    npages * RT_MM_PAGE_SIZE / sizeof(rt_uint32_t);
                page[i].npage    -= npages;
1660
            }
1661
            else if (page[i].npage == npages)
1662
            {
1663
                for (index = i; index < module->page_cnt - 1; index ++)
1664 1665
                {
                    page[index].page_ptr = page[index + 1].page_ptr;
1666
                    page[index].npage    = page[index + 1].npage;
1667 1668
                }
                page[module->page_cnt - 1].page_ptr = RT_NULL;
1669
                page[module->page_cnt - 1].npage    = 0;
1670

1671
                module->page_cnt --;
1672 1673 1674
            }
            else
                RT_ASSERT(RT_FALSE);
1675
            self_module->page_cnt --;
1676 1677 1678 1679 1680

            return;
        }
    }

1681
    /* should not get here */
1682
    RT_ASSERT(RT_FALSE);
qiuyiuestc's avatar
qiuyiuestc 已提交
1683
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1684

1685 1686 1687
/**
 * rt_module_malloc - allocate memory block in free list
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
1688 1689
void *rt_module_malloc(rt_size_t size)
{
1690 1691 1692 1693
    struct rt_mem_head *b, *n, *up;
    struct rt_mem_head **prev;
    rt_uint32_t npage;
    rt_size_t nunits;
1694
    rt_module_t self_module;
1695

1696 1697
    self_module = rt_module_self();
    RT_ASSERT(self_module != RT_NULL);
1698

1699
    RT_DEBUG_NOT_IN_INTERRUPT;
1700

1701
    nunits = (size + sizeof(struct rt_mem_head) - 1) /
1702 1703
             sizeof(struct rt_mem_head)
             + 1;
qiuyiuestc's avatar
qiuyiuestc 已提交
1704

1705 1706
    RT_ASSERT(size != 0);
    RT_ASSERT(nunits != 0);
qiuyiuestc's avatar
qiuyiuestc 已提交
1707

1708
    rt_sem_take(&mod_sem, RT_WAITING_FOREVER);
qiuyiuestc's avatar
qiuyiuestc 已提交
1709

1710
    for (prev = (struct rt_mem_head **)&self_module->mem_list;
1711 1712
         (b = *prev) != RT_NULL;
         prev = &(b->next))
1713 1714 1715 1716
    {
        if (b->size > nunits)
        {
            /* split memory */
1717
            n       = b + nunits;
1718 1719 1720
            n->next = b->next;
            n->size = b->size - nunits;
            b->size = nunits;
1721
            *prev   = n;
qiuyiuestc's avatar
qiuyiuestc 已提交
1722

1723 1724
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_malloc 0x%x, %d\n",
                                           b + 1, size));
1725
            rt_sem_release(&mod_sem);
D
dzzxzz 已提交
1726

1727 1728
            return (void *)(b + 1);
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1729

1730 1731 1732 1733
        if (b->size == nunits)
        {
            /* this node fit, remove this node */
            *prev = b->next;
qiuyiuestc's avatar
qiuyiuestc 已提交
1734

1735 1736
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_malloc 0x%x, %d\n",
                                           b + 1, size));
B
bernard.xiong@gmail.com 已提交
1737

1738
            rt_sem_release(&mod_sem);
D
dzzxzz 已提交
1739

1740 1741 1742
            return (void *)(b + 1);
        }
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1743

1744
    /* allocate pages from system heap */
1745
    npage = (size + sizeof(struct rt_mem_head) + RT_MM_PAGE_SIZE - 1) /
1746
            RT_MM_PAGE_SIZE;
1747 1748
    if ((up = (struct rt_mem_head *)rt_module_malloc_page(npage)) == RT_NULL)
        return RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
1749

1750
    up->size = npage * RT_MM_PAGE_SIZE / sizeof(struct rt_mem_head);
B
bernard.xiong@gmail.com 已提交
1751

1752
    for (prev = (struct rt_mem_head **)&self_module->mem_list;
1753 1754
         (b = *prev) != RT_NULL;
         prev = &(b->next))
1755 1756 1757 1758
    {
        if (b > up + up->size)
            break;
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1759

1760
    up->next = b;
1761
    *prev    = up;
qiuyiuestc's avatar
qiuyiuestc 已提交
1762

1763
    rt_sem_release(&mod_sem);
D
dzzxzz 已提交
1764

1765
    return rt_module_malloc(size);
qiuyiuestc's avatar
qiuyiuestc 已提交
1766 1767
}

1768 1769 1770
/**
 * rt_module_free - free memory block in free list
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
1771 1772
void rt_module_free(rt_module_t module, void *addr)
{
1773 1774 1775 1776 1777 1778
    struct rt_mem_head *b, *n, *r;
    struct rt_mem_head **prev;

    RT_DEBUG_NOT_IN_INTERRUPT;

    RT_ASSERT(addr);
1779
    RT_ASSERT((((rt_uint32_t)addr) & (sizeof(struct rt_mem_head) - 1)) == 0);
1780

1781
    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_free 0x%x\n", addr));
1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804

    rt_sem_take(&mod_sem, RT_WAITING_FOREVER);

    n = (struct rt_mem_head *)addr - 1;
    prev = (struct rt_mem_head **)&module->mem_list;

    while ((b = *prev) != RT_NULL)
    {
        RT_ASSERT(b->size > 0);
        RT_ASSERT(b > n || b + b->size <= n);

        if (b + b->size == n && ((rt_uint32_t)n % RT_MM_PAGE_SIZE != 0))
        {
            if (b + (b->size + n->size) == b->next)
            {
                b->size += b->next->size + n->size;
                b->next = b->next->next;
            }
            else
                b->size += n->size;

            if ((rt_uint32_t)b % RT_MM_PAGE_SIZE == 0)
            {
1805 1806
                int npage =
                    b->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
1807 1808 1809 1810
                if (npage > 0)
                {
                    if ((b->size * sizeof(struct rt_page_info) % RT_MM_PAGE_SIZE) != 0)
                    {
1811
                        rt_size_t nunits = npage *
1812 1813
                                           RT_MM_PAGE_SIZE /
                                           sizeof(struct rt_mem_head);
1814
                        /* split memory */
1815
                        r       = b + nunits;
1816 1817
                        r->next = b->next;
                        r->size = b->size - nunits;
1818
                        *prev   = r;
1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841
                    }
                    else
                    {
                        *prev = b->next;
                    }

                    rt_module_free_page(module, b, npage);
                }
            }

            /* unlock */
            rt_sem_release(&mod_sem);

            return;
        }

        if (b == n + n->size)
        {
            n->size = b->size + n->size;
            n->next = b->next;

            if ((rt_uint32_t)n % RT_MM_PAGE_SIZE == 0)
            {
1842 1843
                int npage =
                    n->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
1844 1845 1846 1847
                if (npage > 0)
                {
                    if ((n->size * sizeof(struct rt_page_info) % RT_MM_PAGE_SIZE) != 0)
                    {
1848
                        rt_size_t nunits = npage *
1849 1850
                                           RT_MM_PAGE_SIZE /
                                           sizeof(struct rt_mem_head);
1851
                        /* split memory */
1852
                        r       = n + nunits;
1853 1854
                        r->next = n->next;
                        r->size = n->size - nunits;
1855
                        *prev   = r;
1856
                    }
1857 1858
                    else
                        *prev = n->next;
1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886

                    rt_module_free_page(module, n, npage);
                }
            }
            else
            {
                *prev = n;
            }

            /* unlock */
            rt_sem_release(&mod_sem);

            return;
        }
        if (b > n + n->size)
            break;

        prev = &(b->next);
    }

    if ((rt_uint32_t)n % RT_MM_PAGE_SIZE == 0)
    {
        int npage = n->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
        if (npage > 0)
        {
            rt_module_free_page(module, n, npage);
            if (n->size % RT_MM_PAGE_SIZE != 0)
            {
1887 1888
                rt_size_t nunits =
                    npage * RT_MM_PAGE_SIZE / sizeof(struct rt_mem_head);
1889
                /* split memory */
1890
                r       = n + nunits;
1891 1892
                r->next = b;
                r->size = n->size - nunits;
1893
                *prev   = r;
1894 1895 1896 1897 1898 1899 1900 1901 1902 1903
            }
            else
            {
                *prev = b;
            }
        }
    }
    else
    {
        n->next = b;
1904
        *prev   = n;
1905 1906 1907 1908
    }

    /* unlock */
    rt_sem_release(&mod_sem);
qiuyiuestc's avatar
qiuyiuestc 已提交
1909 1910
}

1911 1912 1913
/**
 * rt_module_realloc - realloc memory block in free list
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
1914 1915
void *rt_module_realloc(void *ptr, rt_size_t size)
{
1916 1917
    struct rt_mem_head *b, *p, *prev, *tmpp;
    rt_size_t nunits;
1918
    rt_module_t self_module;
1919

1920 1921
    self_module = rt_module_self();
    RT_ASSERT(self_module != RT_NULL);
1922 1923 1924 1925 1926 1927 1928

    RT_DEBUG_NOT_IN_INTERRUPT;

    if (!ptr)
        return rt_module_malloc(size);
    if (size == 0)
    {
1929
        rt_module_free(self_module, ptr);
1930 1931 1932 1933

        return RT_NULL;
    }

1934
    nunits = (size + sizeof(struct rt_mem_head) - 1) /
1935 1936
             sizeof(struct rt_mem_head)
             + 1;
1937 1938 1939 1940 1941 1942 1943 1944 1945
    b = (struct rt_mem_head *)ptr - 1;

    if (nunits <= b->size)
    {
        /* new size is smaller or equal then before */
        if (nunits == b->size)
            return ptr;
        else
        {
1946
            p       = b + nunits;
1947 1948
            p->size = b->size - nunits;
            b->size = nunits;
1949
            rt_module_free(self_module, (void *)(p + 1));
1950 1951 1952 1953 1954 1955 1956

            return (void *)(b + 1);
        }
    }
    else
    {
        /* more space then required */
1957
        prev = (struct rt_mem_head *)self_module->mem_list;
1958 1959 1960 1961
        for (p = prev->next;
             p != (b->size + b) && p != RT_NULL;
             prev = p, p = p->next)
        {
1962
            break;
1963
        }
1964

1965
        /* available block after ap in freelist */
1966 1967 1968
        if (p != RT_NULL &&
            (p->size >= (nunits - (b->size))) &&
            p == (b + b->size))
1969 1970
        {
            /* perfect match */
1971
            if (p->size == (nunits - (b->size)))
1972
            {
1973
                b->size    = nunits;
1974 1975
                prev->next = p->next;
            }
1976
            else  /* more space then required, split block */
1977 1978 1979
            {
                /* pointer to old header */
                tmpp = p;
1980
                p    = b + nunits;
1981 1982 1983

                /* restoring old pointer */
                p->next = tmpp->next;
1984

1985
                /* new size for p */
1986 1987
                p->size    = tmpp->size + b->size - nunits;
                b->size    = nunits;
1988 1989
                prev->next = p;
            }
1990
            self_module->mem_list = (void *)prev;
1991 1992 1993 1994 1995

            return (void *)(b + 1);
        }
        else /* allocate new memory and copy old data */
        {
1996 1997
            if ((p = rt_module_malloc(size)) == RT_NULL)
                return RT_NULL;
1998
            rt_memmove(p, (b + 1), ((b->size) * sizeof(struct rt_mem_head)));
1999
            rt_module_free(self_module, (void *)(b + 1));
2000 2001 2002 2003

            return (void *)(p);
        }
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
2004
}
qiuyiuestc's avatar
qiuyiuestc 已提交
2005 2006 2007

#ifdef RT_USING_FINSH
#include <finsh.h>
2008

D
dzzxzz 已提交
2009
void list_memlist(const char *name)
qiuyiuestc's avatar
qiuyiuestc 已提交
2010
{
2011 2012 2013 2014 2015 2016 2017 2018
    rt_module_t module;
    struct rt_mem_head **prev;
    struct rt_mem_head *b;

    module = rt_module_find(name);
    if (module == RT_NULL)
        return;

2019
    for (prev = (struct rt_mem_head **)&module->mem_list;
2020 2021
         (b = *prev) != RT_NULL;
         prev = &(b->next))
2022 2023 2024
    {
        rt_kprintf("0x%x--%d\n", b, b->size * sizeof(struct rt_mem_head));
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
2025 2026 2027
}
FINSH_FUNCTION_EXPORT(list_memlist, list module free memory information)

D
dzzxzz 已提交
2028
void list_mempage(const char *name)
qiuyiuestc's avatar
qiuyiuestc 已提交
2029
{
2030 2031 2032
    rt_module_t module;
    struct rt_page_info *page;
    int i;
qiuyiuestc's avatar
qiuyiuestc 已提交
2033

2034 2035 2036
    module = rt_module_find(name);
    if (module == RT_NULL)
        return;
qiuyiuestc's avatar
qiuyiuestc 已提交
2037

2038
    page = (struct rt_page_info *)module->page_array;
qiuyiuestc's avatar
qiuyiuestc 已提交
2039

2040
    for (i = 0; i < module->page_cnt; i ++)
2041 2042 2043
    {
        rt_kprintf("0x%x--%d\n", page[i].page_ptr, page[i].npage);
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
2044 2045
}
FINSH_FUNCTION_EXPORT(list_mempage, list module using memory page information)
2046
#endif /* RT_USING_FINSH */
qiuyiuestc's avatar
qiuyiuestc 已提交
2047

2048
#endif /* RT_USING_SLAB */
qiuyiuestc's avatar
qiuyiuestc 已提交
2049 2050

#endif