U-BootとLinuxカーネルのインタラクション
14300 ワード
U-BootとLinuxカーネルのインタラクション
説明:本明細書で使用するU-Bootのバージョンは1.1.6であり、プラットフォームはS 3 C 2440である.
目次
一、紹介
1.1タグリスト
二、タグ保管の住所を設定する
2.1関連する構造体定義
2.2タグ格納先の設定
三、タグの設定
3.1タグATAGの設定CORE
3.2メモリタグATAGの設定MEM
3.3コマンドラインタグATAGの設定CMDLINE
3.4 ATAGの設定NONE
一、紹介
U-BootとLinuxカーネルのインタラクションは一方向であり,U-Bootは各種パラメータをナハに伝達する.同時に実行できないため、転送方法は1つしかありません.U-Bootはパラメータを所定の場所に置いた後、カーネルを起動し、カーネルが起動した後、この場所からパラメータを取得します.
1.1タグリスト
パラメータを格納する場所を約束するほか,パラメータの構造を規定する.Linux2.4.x以降のカーネルは、パラメータをタグリスト(tagged list)として渡します.タグはデータ構造です.タグリストは、隣接して格納されている複数のタグです.タグリストはATAG_をタグするCOREで始まり、ATAGE_でNONE終了.
タグ付けされたデータ構造はtagであり、これは偶発的なtagである.ヘッダ構造と結合体(union)組成.tag_ヘッダ構造体は、メモリを表すかコマンドラインパラメータを表すかなど、タグのタイプと長さを表す.メモリ=を表すときにtag_を使用するなど、異なるタイプのタグに対して異なる連合体を使用します.men 32は、コマンドラインの場合tag_を使用することを示すcmdline.その定義はinclude/asm-arm/setupである.cファイルにあります.
二、タグ保管の住所を設定する
2.1関連する構造体定義
構造体bdには、タグが格納されたアドレスが格納されている.bd構造体はgd構造体の1つであり、include/asm-arm/global_に定義されたgd構造体を見てみましょう.data.hファイル内:
2.2タグ格納先の設定
board/smdk 2410/smdk 2410.cのboard_init関数はbi_を設定しましたboot_paramsパラメータ:
三、タグの設定
U-BootはbootmコマンドでLinuxカーネルを起動し、bootmコマンドは吼えにdo_を呼び出す.bootm_linux関数を使用してカーネルを起動します.do_bootm_linux関数はlib_に定義されたタグを設定します.arm/armlinux.c中:
3.1タグATAGの設定CORE
タグリストはATAG_をタグするCORE開始
3.2メモリタグATAGの設定MEM
board/smdk 2410/smdk 2410.cのdram_init関数はbdのbi_を設定しましたdram構造体:
次に、メモリタグの構造体を示します.
3.3コマンドラインタグATAGの設定CMDLINE
コマンドラインは、カーネルの動作を制御する文字列です.例えば「root=/dev/mtdblock 2 init=/linuxrc console=ttySAC 0」は、ルートファイルシステムがMTD 2パーティション上でシステム起動後に実行する最初のプログラムが/linuxrcであり、コンソールがttySAC 0であることを示す.
3.4 ATAGの設定NONE
タグリストはATAG_をタグするNONE紹介.
説明:本明細書で使用するU-Bootのバージョンは1.1.6であり、プラットフォームはS 3 C 2440である.
目次
一、紹介
1.1タグリスト
二、タグ保管の住所を設定する
2.1関連する構造体定義
2.2タグ格納先の設定
三、タグの設定
3.1タグATAGの設定CORE
3.2メモリタグATAGの設定MEM
3.3コマンドラインタグATAGの設定CMDLINE
3.4 ATAGの設定NONE
一、紹介
U-BootとLinuxカーネルのインタラクションは一方向であり,U-Bootは各種パラメータをナハに伝達する.同時に実行できないため、転送方法は1つしかありません.U-Bootはパラメータを所定の場所に置いた後、カーネルを起動し、カーネルが起動した後、この場所からパラメータを取得します.
1.1タグリスト
パラメータを格納する場所を約束するほか,パラメータの構造を規定する.Linux2.4.x以降のカーネルは、パラメータをタグリスト(tagged list)として渡します.タグはデータ構造です.タグリストは、隣接して格納されている複数のタグです.タグリストはATAG_をタグするCOREで始まり、ATAGE_でNONE終了.
タグ付けされたデータ構造はtagであり、これは偶発的なtagである.ヘッダ構造と結合体(union)組成.tag_ヘッダ構造体は、メモリを表すかコマンドラインパラメータを表すかなど、タグのタイプと長さを表す.メモリ=を表すときにtag_を使用するなど、異なるタイプのタグに対して異なる連合体を使用します.men 32は、コマンドラインの場合tag_を使用することを示すcmdline.その定義はinclude/asm-arm/setupである.cファイルにあります.
/*
* The new way of passing information: a list of tagged entries
*/
/* The list ends with an ATAG_NONE node. */
#define ATAG_NONE 0x00000000
struct tag_header {
u32 size;
u32 tag;
};
/* The list must start with an ATAG_CORE node */
#define ATAG_CORE 0x54410001
struct tag_core {
u32 flags; /* bit 0 = read-only */
u32 pagesize;
u32 rootdev;
};
/* it is allowed to have multiple ATAG_MEM nodes */
#define ATAG_MEM 0x54410002
struct tag_mem32 {
u32 size;
u32 start; /* physical start address */
};
/* VGA text type displays */
#define ATAG_VIDEOTEXT 0x54410003
struct tag_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;
};
/* describes how the ramdisk will be used in kernel */
#define ATAG_RAMDISK 0x54410004
struct tag_ramdisk {
u32 flags; /* bit 0 = load, bit 1 = prompt */
u32 size; /* decompressed ramdisk size in _kilo_ bytes */
u32 start; /* starting block of floppy-based RAM disk image */
};
/* describes where the compressed ramdisk image lives (virtual address) */
/*
* this one accidentally used virtual addresses - as such,
* its depreciated.
*/
#define ATAG_INITRD 0x54410005
/* describes where the compressed ramdisk image lives (physical address) */
#define ATAG_INITRD2 0x54420005
struct tag_initrd {
u32 start; /* physical start address */
u32 size; /* size of compressed ramdisk image in bytes */
};
/* board serial number. "64 bits should be enough for everybody" */
#define ATAG_SERIAL 0x54410006
struct tag_serialnr {
u32 low;
u32 high;
};
/* board revision */
#define ATAG_REVISION 0x54410007
struct tag_revision {
u32 rev;
};
/* initial values for vesafb-type framebuffers. see struct screen_info
* in include/linux/tty.h
*/
#define ATAG_VIDEOLFB 0x54410008
struct tag_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;
};
/* command line: \0 terminated string */
#define ATAG_CMDLINE 0x54410009
struct tag_cmdline {
char cmdline[1]; /* this is the minimum size */
};
/* acorn RiscPC specific information */
#define ATAG_ACORN 0x41000101
struct tag_acorn {
u32 memc_control_reg;
u32 vram_pages;
u8 sounddefault;
u8 adfsdrives;
};
/* footbridge memory clock, see arch/arm/mach-footbridge/arch.c */
#define ATAG_MEMCLK 0x41000402
struct tag_memclk {
u32 fmemclk;
};
struct tag {
struct tag_header hdr;
union {
struct tag_core core;
struct tag_mem32 mem;
struct tag_videotext videotext;
struct tag_ramdisk ramdisk;
struct tag_initrd initrd;
struct tag_serialnr serialnr;
struct tag_revision revision;
struct tag_videolfb videolfb;
struct tag_cmdline cmdline;
/*
* Acorn specific
*/
struct tag_acorn acorn;
/*
* DC21285 specific
*/
struct tag_memclk memclk;
} u;
};
#define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size))
#define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2) //???
二、タグ保管の住所を設定する
2.1関連する構造体定義
構造体bdには、タグが格納されたアドレスが格納されている.bd構造体はgd構造体の1つであり、include/asm-arm/global_に定義されたgd構造体を見てみましょう.data.hファイル内:
typedef struct global_data {
bd_t *bd;// , , u-boot.h
unsigned long flags;// ,
unsigned long baudrate;//
unsigned long have_console;
/* serial_init() was called , 1 */
unsigned long reloc_off;
/*
*Relocation Offset , , 0
*/
unsigned long env_addr; /* */
unsigned long env_valid; /* CRC */
unsigned long fb_base; /* */
#ifdef CONFIG_VFD
unsigned char vfd_type; /* */
#endif
#if 0
unsigned long cpu_clk; /*cpu */
unsigned long bus_clk; //
unsigned long ram_size; /* RAM size */
unsigned long reset_status; /* reset status register at boot */
#endif
void **jt; /* jump table , " "*/
} gd_t;
受け取って、include/asm-arm/u-bootで定義されたbd構造体を見てみましょう.hファイル内:typedef struct bd_info {
int bi_baudrate; /* */
unsigned long bi_ip_addr; /* IP */
unsigned char bi_enetaddr[6]; /* MAC */
struct environment_s *bi_env;
ulong bi_arch_number; /* id*/
ulong bi_boot_params; /* */
struct /* RAM */
{
ulong start;
ulong size;
}bi_dram[CONFIG_NR_DRAM_BANKS];
#ifdef CONFIG_HAS_ETH1
/* second onboard ethernet port */
unsigned char bi_enet1addr[6];
#endif
} bd_t;
2.2タグ格納先の設定
board/smdk 2410/smdk 2410.cのboard_init関数はbi_を設定しましたboot_paramsパラメータ:
int board_init (void)
{
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();// ,
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();// GPIO
/* to reduce PLL lock time, adjust the LOCKTIME register */
clk_power->LOCKTIME = 0xFFFFFF;
/* configure MPLL */
clk_power->MPLLCON = ((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV);
/* some delay between MPLL and UPLL */
delay (4000);
/* configure UPLL */
clk_power->UPLLCON = ((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV);
/* some delay between MPLL and UPLL */
delay (8000);
/* set up the I/O ports */
gpio->GPACON = 0x007FFFFF;
gpio->GPBCON = 0x00044555;
gpio->GPBUP = 0x000007FF;
gpio->GPCCON = 0xAAAAAAAA;
gpio->GPCUP = 0x0000FFFF;
gpio->GPDCON = 0xAAAAAAAA;
gpio->GPDUP = 0x0000FFFF;
gpio->GPECON = 0xAAAAAAAA;
gpio->GPEUP = 0x0000FFFF;
gpio->GPFCON = 0x000055AA;
gpio->GPFUP = 0x000000FF;
gpio->GPGCON = 0xFF95FFBA;
gpio->GPGUP = 0x0000FFFF;
gpio->GPHCON = 0x002AFAAA;
gpio->GPHUP = 0x000007FF;
/* arch number of SMDK2410-Board */
gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
/* adress of boot parameters */
gd->bd->bi_boot_params = 0x30000100;
icache_enable(); // cpu/arm920t/cpu.c
dcache_enable();
return 0;
}
三、タグの設定
U-BootはbootmコマンドでLinuxカーネルを起動し、bootmコマンドは吼えにdo_を呼び出す.bootm_linux関数を使用してカーネルを起動します.do_bootm_linux関数はlib_に定義されたタグを設定します.arm/armlinux.c中:
void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
ulong addr, ulong *len_ptr, int verify)
{
ulong len = 0, checksum;
ulong initrd_start, initrd_end;
ulong data;
void (*theKernel)(int zero, int arch, uint params);
image_header_t *hdr = &header;
bd_t *bd = gd->bd;
#ifdef CONFIG_CMDLINE_TAG
char *commandline = getenv ("bootargs");
#endif
theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);
kernal
/*
* Check if there is an initrd image
*/
initrd , , , 。
initial RAM disk Linux RAM (initrd) , 。initrd , , initrd RAM , 。 Linux ,initrd 。
if (argc >= 3) {
SHOW_BOOT_PROGRESS (9);
addr = simple_strtoul (argv[2], NULL, 16);
printf ("## Loading Ramdisk Image at %08lx ...
", addr);
/* Copy header so we can blank CRC field for re-calculation */
#ifdef CONFIG_HAS_DATAFLASH
if (addr_dataflash (addr)) {
read_dataflash (addr, sizeof (image_header_t),
(char *) &header);
} else
#endif
memcpy (&header, (char *) addr,
sizeof (image_header_t));
if (ntohl (hdr->ih_magic) != IH_MAGIC) {
printf ("Bad Magic Number
");
SHOW_BOOT_PROGRESS (-10);
do_reset (cmdtp, flag, argc, argv);
}
data = (ulong) & header;
len = sizeof (image_header_t);
checksum = ntohl (hdr->ih_hcrc);
hdr->ih_hcrc = 0;
if (crc32 (0, (unsigned char *) data, len) != checksum) {
printf ("Bad Header Checksum
");
SHOW_BOOT_PROGRESS (-11);
do_reset (cmdtp, flag, argc, argv);
}
SHOW_BOOT_PROGRESS (10);
print_image_hdr (hdr);
data = addr + sizeof (image_header_t);
len = ntohl (hdr->ih_size);
#ifdef CONFIG_HAS_DATAFLASH
if (addr_dataflash (addr)) {
read_dataflash (data, len, (char *) CFG_LOAD_ADDR);
data = CFG_LOAD_ADDR;
}
#endif
if (verify) {
ulong csum = 0;
printf (" Verifying Checksum ... ");
csum = crc32 (0, (unsigned char *) data, len);
if (csum != ntohl (hdr->ih_dcrc)) {
printf ("Bad Data CRC
");
SHOW_BOOT_PROGRESS (-12);
do_reset (cmdtp, flag, argc, argv);
}
printf ("OK
");
}
SHOW_BOOT_PROGRESS (11);
if ((hdr->ih_os != IH_OS_LINUX) ||
(hdr->ih_arch != IH_CPU_ARM) ||
(hdr->ih_type != IH_TYPE_RAMDISK)) {
printf ("No Linux ARM Ramdisk Image
");
SHOW_BOOT_PROGRESS (-13);
do_reset (cmdtp, flag, argc, argv);
}
#if defined(CONFIG_B2) || defined(CONFIG_EVB4510) || defined(CONFIG_ARMADILLO)
/*
*we need to copy the ramdisk to SRAM to let Linux boot
*/
memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);
data = ntohl(hdr->ih_load);
#endif /* CONFIG_B2 || CONFIG_EVB4510 */
/*
* Now check if we have a multifile image
*/
} else if ((hdr->ih_type == IH_TYPE_MULTI) && (len_ptr[1])) {
ulong tail = ntohl (len_ptr[0]) % 4;
int i;
SHOW_BOOT_PROGRESS (13);
/* skip kernel length and terminator */
data = (ulong) (&len_ptr[2]);
/* skip any additional image length fields */
for (i = 1; len_ptr[i]; ++i)
data += 4;
/* add kernel length, and align */
data += ntohl (len_ptr[0]);
if (tail) {
data += 4 - tail;
}
len = ntohl (len_ptr[1]);
} else {
/*
* no initrd image
*/
SHOW_BOOT_PROGRESS (14);
len = data = 0;
}
#ifdef DEBUG
if (!data) {
printf ("No initrd
");
}
#endif
if (data) {
initrd_start = data;
initrd_end = initrd_start + len;
} else {
initrd_start = 0;
initrd_end = 0;
}
SHOW_BOOT_PROGRESS (15);
debug ("## Transferring control to Linux (at address %08lx) ...
",
(ulong) theKernel);
#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
defined (CONFIG_CMDLINE_TAG) || \
defined (CONFIG_INITRD_TAG) || \
defined (CONFIG_SERIAL_TAG) || \
defined (CONFIG_REVISION_TAG) || \
defined (CONFIG_LCD) || \
defined (CONFIG_VFD)
setup_start_tag (bd); tag, Linux
#ifdef CONFIG_SERIAL_TAG
setup_serial_tag (¶ms);
#endif
#ifdef CONFIG_REVISION_TAG
setup_revision_tag (¶ms);
#endif
#ifdef CONFIG_SETUP_MEMORY_TAGS
setup_memory_tags (bd);
#endif
#ifdef CONFIG_CMDLINE_TAG
setup_commandline_tag (bd, commandline);
#endif
#ifdef CONFIG_INITRD_TAG
if (initrd_start && initrd_end)
setup_initrd_tag (bd, initrd_start, initrd_end);
#endif
#if defined (CONFIG_VFD) || defined (CONFIG_LCD)
setup_videolfb_tag ((gd_t *) gd);
#endif
setup_end_tag (bd);
#endif
/* we assume that the kernel is in place */
printf ("
Starting kernel ...
");
#ifdef CONFIG_USB_DEVICE
{
extern void udc_disconnect (void);
udc_disconnect ();
}
#endif
cleanup_before_linux (); cpu/arm920t/cpu.c
:
R0: 0
R1: ID, ARM(bd->bi_arch_number)
R2: (bd->bi_boot_params)
theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
}
3.1タグATAGの設定CORE
タグリストはATAG_をタグするCORE開始
static void setup_start_tag (bd_t *bd)
{
params = (struct tag *) bd->bi_boot_params;
params->hdr.tag = ATAG_CORE;
params->hdr.size = tag_size (tag_core);
params->u.core.flags = 0;
params->u.core.pagesize = 0;
params->u.core.rootdev = 0;
params = tag_next (params);//
}
3.2メモリタグATAGの設定MEM
board/smdk 2410/smdk 2410.cのdram_init関数はbdのbi_を設定しましたdram構造体:
int dram_init (void)
{
gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
return 0;
}
次に、メモリタグの構造体を示します.
static void setup_memory_tags (bd_t *bd)
{
int i;
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
params->hdr.tag = ATAG_MEM;
params->hdr.size = tag_size (tag_mem32);
params->u.mem.start = bd->bi_dram[i].start;
params->u.mem.size = bd->bi_dram[i].size;
params = tag_next (params);
}
}
3.3コマンドラインタグATAGの設定CMDLINE
コマンドラインは、カーネルの動作を制御する文字列です.例えば「root=/dev/mtdblock 2 init=/linuxrc console=ttySAC 0」は、ルートファイルシステムがMTD 2パーティション上でシステム起動後に実行する最初のプログラムが/linuxrcであり、コンソールがttySAC 0であることを示す.
static void setup_commandline_tag (bd_t *bd, char *commandline)
{
char *p;
if (!commandline)
return;
/* eat leading white space */
for (p = commandline; *p == ' '; p++);
/* skip non-existent command lines so the kernel will still
* use its default command line.
*/
if (*p == '\0')
return;
params->hdr.tag = ATAG_CMDLINE;
params->hdr.size =
(sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;
strcpy (params->u.cmdline.cmdline, p);
params = tag_next (params);
}
3.4 ATAGの設定NONE
タグリストはATAG_をタグするNONE紹介.
static void setup_end_tag (bd_t *bd)
{
params->hdr.tag = ATAG_NONE;
params->hdr.size = 0;
}