The website "dmilvdv.narod.ru." is not registered with uCoz.
If you are absolutely sure your website must be here,
please contact our Support Team.
If you were searching for something on the Internet and ended up here, try again:

About uCoz web-service

Community

Legal information

B. Полный пример

B. Полный пример

Предыдущая  Содержание  Следующая V*D*V

Это рабочий пример простого загрузчика и он показывает всю информацию, описанную в этом документе. Для реального загрузчика может потребоваться больше кода, этот пример чисто иллюстративен.

 

Код этого примера распространяется под лицензией BSD, может быть свободно скопирован и использован, если это необходимо.

 

/* example.c

 * пример кода загрузчика для ARM Linux

 * этот пример распространяется под лицензией BSD

 */

 

/* список возможных тэгов */

#define ATAG_NONE      0x00000000

#define ATAG_CORE      0x54410001

#define ATAG_MEM       0x54410002

#define ATAG_VIDEOTEXT 0x54410003

#define ATAG_RAMDISK   0x54410004

#define ATAG_INITRD2   0x54420005

#define ATAG_SERIAL    0x54410006

#define ATAG_REVISION  0x54410007

#define ATAG_VIDEOLFB  0x54410008

#define ATAG_CMDLINE   0x54410009

 

/* структуры для каждого тэга */

struct atag_header {

    u32 size; /* размер тэга в словах, включая этот заголовок */

    u32 tag;  /* тип тэга */

};

 

struct atag_core {

    u32 flags;

    u32 pagesize;

    u32 rootdev;

};

 

struct atag_mem {

    u32 size;

    u32 start;

};

 

struct atag_videotext {

    u8 x;

    u8 y;

    u16 video_page;

    u8 video_mode;

    u8 video_cols;

    u16 video_ega_bx;

    u8 video_lines;

    u8 video_isvga;

    u16 video_points;

};

 

struct atag_ramdisk {

    u32 flags;

    u32 size;

    u32 start;

};

 

struct atag_initrd2 {

    u32 start;

    u32 size;

};

 

struct atag_serialnr {

    u32 low;

    u32 high;

};

 

struct atag_revision {

    u32 rev;

};

 

struct atag_videolfb {

    u16 lfb_width;

    u16 lfb_height;

    u16 lfb_depth;

    u16 lfb_linelength;

    u32 lfb_base;

    u32 lfb_size;

    u8 red_size;

    u8 red_pos;

    u8 green_size;

    u8 green_pos;

    u8 blue_size;

    u8 blue_pos;

    u8 rsvd_size;

    u8 rsvd_pos;

};

 

struct atag_cmdline {

    char cmdline[1];

};

 

struct atag {

    struct atag_header hdr;

    union {

        struct atag_core core;

        struct atag_mem mem;

        struct atag_videotext videotext;

        struct atag_ramdisk ramdisk;

        struct atag_initrd2 initrd2;

        struct atag_serialnr serialnr;

        struct atag_revision revision;

        struct atag_videolfb videolfb;

        struct atag_cmdline cmdline;

    } u;

};

 

#define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size))

#define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)

static struct atag *params; /* указывает адрес текущего тэга */

 

static void

setup_core_tag(void * address,long pagesize)

{

    params = (struct tag *)address; /* Начальные параметры для старта */

    params->hdr.tag = ATAG_CORE; /* начинаем с основного тэга */

    params->hdr.size = tag_size(atag_core); /* размер тэга */

    params->u.core.flags = 1; /* обеспечить только чтение */

    params->u.core.pagesize = pagesize; /* размер системной страницы (4k) */

    params->u.core.rootdev = 0; /* нулевое корневое устройство (обычно перезаписывается)

    params = tag_next(params); /* передвинуть указатель на следующий тэг */

}

 

static void

setup_ramdisk_tag(u32_t size)

{

    params->hdr.tag = ATAG_RAMDISK; /* тэг Ramdisk-а */

    params->hdr.size = tag_size(atag_ramdisk); /* размер тэга */

    params->u.ramdisk.flags = 0; /* Загрузить ramdisk */

    params->u.ramdisk.size = size; /* Размер декомпрессированного ramdisk */

    params->u.ramdisk.start = 0; /* Не используется */

    params = tag_next(params); /* передвинуть указатель на следующий тэг */

}

 

static void

setup_initrd2_tag(u32_t start, u32_t size)

{

    params->hdr.tag = ATAG_INITRD2; /* Тэг Initrd2 */

    params->hdr.size = tag_size(atag_initrd2); /* размер тэга */

    params->u.initrd2.start = start; /* физический старт */

    params->u.initrd2.size = size; /* размер скомпрессированного ramdisk */

    params = tag_next(params); /* передвинуть указатель на следующий тэг */

}

 

static void

setup_mem_tag(u32_t start, u32_t len)

{

    params->hdr.tag = ATAG_MEM; /* Тэг памяти */

    params->hdr.size = tag_size(atag_mem); /* размер тэга */

    params->u.mem.start = start; /* Начало области памяти (физический адрес)

    params->u.mem.size = len; /* Размер области */

    params = tag_next(params); /* передвинуть указатель на следующий тэг */

}

 

static void

setup_cmdline_tag(const char * line)

{

    int linelen = strlen(line);

    if(!linelen)

        return; /* не вставлять тэг для пустой строки */

    params->hdr.tag = ATAG_CMDLINE; /* Тэг командной строки */

    params->hdr.size = (sizeof(struct atag_header) + linelen + 1 + 4) >> 2; /* размер тэга */

    strcpy(params->u.cmdline.cmdline,line); /* поместить командную строчку в тэг */

    params = tag_next(params); /* передвинуть указатель на следующий тэг */

}

 

static void

setup_end_tag(void)

{

    params->hdr.tag = ATAG_NONE; /* Пустой тэг заканчивает список */

    params->hdr.size = 0; /* нулевая длина */

}

 

#define DRAM_BASE 0x10000000

#define ZIMAGE_LOAD_ADDRESS DRAM_BASE + 0x8000

#define INITRD_LOAD_ADDRESS DRAM_BASE + 0x800000

 

static void

setup_tags(parameters)

{

    setup_core_tag(parameters, 4096); /* стандартный основной тэг, размер страницы 4k */

    setup_mem_tag(DRAM_BASE, 0x4000000); /* 64Mb с адреса 0x10000000 */

    setup_mem_tag(DRAM_BASE + 0x8000000, 0x4000000); /* 64Mb с адреса 0x18000000 */

    setup_ramdisk_tag(4096); /* создать 4Mb ramdisk */

    setup_initrd2_tag(INITRD_LOAD_ADDRESS, 0x100000); /* компрессированные данные 1Mb */

    setup_cmdline_tag("root=/dev/ram0"); /* командная строчка, устанавливающая корневое устройство */

    setup_end_tag(void); /* завершающий тэг */

}

 

int

start_linux(char *name,char *rdname)

{

    void (*theKernel)(int zero, int arch, u32 params);

    u32 exec_at = (u32)-1;

    u32 parm_at = (u32)-1;

    u32 machine_type;

    exec_at = ZIMAGE_LOAD_ADDRESS;

    parm_at = DRAM_BASE + 0x100

    load_image(name, exec_at); /* скопировать образ в RAM */

    load_image(rdname, INITRD_LOAD_ADDRESS); /* скопировать образ начального ramdisk в RAM */

    setup_tags(parm_at); /* установить параметры */

    machine_type = get_mach_type(); /* получить тип машины */

    irq_shutdown(); /* остановить прерывания */

    cpu_op(CPUOP_MMUCHANGE, NULL); /* выключить MMU */

    theKernel = (void (*)(int, int, u32))exec_at; /* установить адрес ядра */

    theKernel(0, machine_type, parm_at); /* передать управление ядру с установленными регистрами */

    return 0;

}

 

Предыдущая  Содержание  Следующая