VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > 汇编语言 >
  • linux驱动系列之arm汇编

     在arm平台学习linux时,会遇到arm汇编指令,arm汇编指令与8086汇编指令很多地方都不同,在此记下来以免后面忘了,同时在学习了汇编指令之后分析一些汇编指令编写的代码。

一、相对跳转指令b、bl

       b、bl指令都实现短跳转,bl指令执行后会在链接寄存器r14中保存下一条指令的地址。

二、数据传送指令mov

  mov指令会把一个寄存器的数赋值给另一个寄存器,或者把一个常数传递给另一个寄存器。

  如:mov  r0,r1  //将r1中的值传递给r0,mov r0,#0xff //将常数0xff传递给r0寄存器。

  mov指令传递的常数必须能够用立即数表示,当不知道一个数是否能够用“立即数传递”时,可以用ldr指令进行传递。

  如:ldr r0,=0xff。

三、内存访问指令str、ldr、ldm、stm

  ldr指令从内存中读取数到寄存器中,str指令将寄存器中的数传递到内存中,ldr、str指令操作的数都是32位的。ldm、stm是批量内存访问指令,用一个指令就能访问多个数据。下面是从s3c2440 datasheet上面的截图

  {cond}表示指令的执行条件

  Rn中保存内存地址,如果后面有!指令执行后会更新为下一个内存单元的地址

  <Rlist>寄存器列表对于ldm指令相当于将内存的数据取出放入列表中的寄存器中,stm指令相当于将列表中的寄存器中的值放入内存中。

  {^}有两种含义:如果<Rlist>有PC寄存器时,它表示指令执行后,spsr寄存器的值会自动复制cpsr寄存器中,这个常用于从中断处理函数中返回。如果<Rlist>中没有PC寄存器时,{^}表示操作的是用户模式下的寄存器,不是特权模式下的寄存器。

  指令中列表中的寄存器与内存对应关系为:编号底的寄存器对应低地址内存单元,编号搞的对应高地址内存单元。

四、加减指令add、sub

   如:add r0,r1,#0xff //r0=r1+0xff  sub r0,r1,#0xff  //表示r0=r1-0xff

五、程序状态寄存器访问指令msr、mrs

     arm有个程序状态寄存器cpsr,它用来控制处理器的工作模式和设置中断的总开关。

  msr cpsr,r0  //复制r0到cpsr中

  mrs r0,cpsr //复制cpsr到r0中

六、伪指令

  .gloabl  _start

  _start:

  .text

  .extern main

  .gloabl将本文件中的某个程序定义为全局的

  .extern 将某个变量或者函数引用到本文件中

  .text 表示下面的语句都属于代码段

八、uboot启动过程分析

   在看了韦东山老师的书和视频后,对汇编指令及bootloader的工作流程有了一个新的认识,我们接触比较的bootloader就是电脑的bios了,bootloader就是一段将我们硬盘上的代码搬运到内存中指定位置运行的程序。

  在说硬盘内存这些概念时我们首先要对s3c24xx或者其他的微处理器的存储空间有一个大致的了解。我做实验主要用的是2440,下面也就2440进行说明。在2440中我们一般使用三种存储设备:SDRAM、Nandflash、Norflash。这三个存储设备相对于我们平常的PC就是:SDRAM====>内存条,(Nandflash、Norflash)====>硬盘,对于Nandflash和Norflash的区别主要是前者不能直接运行代码,后者代码可以直接运行但是不能进行写数据,所以我们常常将Nandflash 存放程序,Norflash存放数据。

  对于存储空间2440有一个专门的存储控制器,

 

  一般我们把Norflash、Nandflash都与nGCS0相连,然后通过选择OM0、OM1选择哪种启动方式,如果选择Norflash我们的代码就会从Norflash的0地址开始执行,如果选择Nandflash我们的代码会被处理器将Nandflash的前4k拷贝到芯片内部的4k RAM中,然后程序在内部4k RAM中开始执行,这个拷贝过程是一个硬件过程,芯片内部自动完成。由于只有4k大小如果我们的程序小于4k,我们就直接让其在芯片内部RAM中执行,如果我们的代码大于4k,一般我们会用4k大小的程序将Nandflash里面的其余部分程序直接拷贝到SDRAM(0x3000 0000)中执行。

  我们的bootloader肯定是大于4k的,说以如果在Nandflash中运行我们就必须在4k 大小的代码中将bootloader拷贝到SDRAM,然后在SDRAM中将Nandflash 中的Kernerl拷贝到SDRAM中完成内核的启动,大的流程就如前面所说,但是具体在实现的过程中有很多的小细节。

8.1 bootloader启动前的准备

  1、关看门狗

  2、设置时钟

  3、初始化SDRAM

  4、重定位将bootloader的代码从Nandflash中拷贝到SDRAM中

  5、执行main

      ====》在main函数中所做的工作

          1、初始化串口(因为要加载内核需要打印一些信息,内核没有串口初始化的代码所以需要在内核启动前进行初始化)

          2、从Nandflash中将内核读入SDRAM

          3、设置参数(这个工作非常重要,因为内核在启动过程中需要设置启动参数比如:设置内存标记(内存的起始地址、内存大小)、设置命令行标记(命令行就是一个字符串,用于控制内核的一些行为。比如"noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0" 表示根文件系统在MTD3分区上,启动系统后执行的第一个程序是linuxrc,控制台为ttySAC0(第一个串口)))。在启动时bootloader与Kernel的交互式单项的所以只能是在bootloader启动阶段将我们用于设置内核的参数放在内存的某个地方,bootloader与Kernel约定好内核启动时就在这个地方去读取这些配置参数完成启动,一般这些参数存放在SDRAM 0x3100 0000地址上。

复制代码
 1 /* 3. 跳转执行 */
 2 puts("Boot kernel\n\r");
 3 theKernel = (void (*)(int, int, unsigned int))0x30008000;
 4 theKernel(0, 362, 0x30000100);  
 5 /* 
 6  *  mov r0, #0
 7  *  ldr r1, =362
 8  *  ldr r2, =0x30000100
 9 *  mov pc, #0x30008000 
10  */
复制代码

    第3行代码就是将函数指针的首地址放到内核存放的内存首地址中去执行,下面的参数因为是函数调用所以会把我们上面说的bootloader与Kernel交互的设置参数保存在内存中的地址0x3000 0100放在r2寄存器中,内核执行时会从r2寄存器中取出地址然后找到我们在bootloader启动阶段存放的设置参数,这个过程相当的巧妙,主要是利用了函数调用时参数一般会保存在r0-r3,被调用的子程序返回前无需回复r0-r3的内容。  

  参考主要代码:

  1、bootloader启动汇编部分

复制代码
 1 #define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x01<<4)|(0x02))
 2 #define S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))
 3 #define MEM_CTL_BASE    0x48000000
 4 
 5 .text
 6 .global _start
 7 _start:
 8 
 9 /* 1. 关看门狗 */
10     ldr r0, =0x53000000
11     mov r1, #0
12     str r1, [r0]
13 
14 /* 2. 设置时钟 */
15     ldr r0, =0x4c000014
16     //    mov r1, #0x03;              // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
17     mov r1, #0x05;              // FCLK:HCLK:PCLK=1:4:8
18     str r1, [r0]
19        
20     /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
21     mrc    p15, 0, r1, c1, c0, 0        /* 读出控制寄存器 */ 
22     orr    r1, r1, #0xc0000000            /* 设置为“asynchronous bus mode” */
23     mcr    p15, 0, r1, c1, c0, 0        /* 写入控制寄存器 */
24 
25     /* MPLLCON = S3C2440_MPLL_200MHZ */
26     ldr r0, =0x4c000004
27     ldr r1, =S3C2440_MPLL_400MHZ
28     str r1, [r0]
29 
30     /* 启动ICACHE */
31     mrc p15, 0, r0, c1, c0, 0    @ read control reg
32     orr r0, r0, #(1<<12)
33     mcr    p15, 0, r0, c1, c0, 0   @ write it back
34 
35 
36 /* 3. 初始化SDRAM */
37     ldr r0, =MEM_CTL_BASE
38     adr r1, sdram_config     /* sdram_config的当前地址 */
39     add r3, r0, #(13*4)
40 1:
41     ldr r2, [r1], #4
42     str r2, [r0], #4
43     cmp r0, r3
44     bne 1b
45 
46 /* 4. 重定位 : 把bootloader本身的代码从flash复制到它的链接地址去 */
47     ldr sp, =0x34000000
48 
49     bl nand_init
50 
51     mov r0, #0
52     ldr r1, =_start
53     ldr r2, =__bss_start
54     sub r2, r2, r1
55     
56     bl copy_code_to_sdram
57     bl clear_bss
58     
59 /* 5. 执行main */
60     ldr lr, =halt
61     ldr pc, =main
62 halt:
63     b halt
64 
65 sdram_config:
66     .long 0x22011110     //BWSCON
67     .long 0x00000700     //BANKCON0
68     .long 0x00000700     //BANKCON1
69     .long 0x00000700     //BANKCON2
70     .long 0x00000700     //BANKCON3  
71     .long 0x00000700     //BANKCON4
72     .long 0x00000700     //BANKCON5
73     .long 0x00018005     //BANKCON6
74     .long 0x00018005     //BANKCON7
75     .long 0x008C04F4     // REFRESH
76     .long 0x000000B1     //BANKSIZE
77     .long 0x00000030     //MRSRB6
78     .long 0x00000030     //MRSRB7
复制代码

  2、main函数部分

复制代码
  1 #include "setup.h"
  2 
  3 extern void uart0_init(void);
  4 extern void nand_read(unsigned int addr, unsigned char *buf, unsigned int len);
  5 extern void puts(char *str);
  6 extern void puthex(unsigned int val);
  7 
  8 
  9 static struct tag *params;
 10 
 11 void setup_start_tag(void)
 12 {
 13     params = (struct tag *)0x30000100;
 14 
 15     params->hdr.tag = ATAG_CORE;
 16     params->hdr.size = tag_size (tag_core);
 17 
 18     params->u.core.flags = 0;
 19     params->u.core.pagesize = 0;
 20     params->u.core.rootdev = 0;
 21 
 22     params = tag_next (params);
 23 }
 24 
 25 void setup_memory_tags(void)
 26 {
 27     params->hdr.tag = ATAG_MEM;
 28     params->hdr.size = tag_size (tag_mem32);
 29     
 30     params->u.mem.start = 0x30000000;
 31     params->u.mem.size  = 64*1024*1024;
 32     
 33     params = tag_next (params);
 34 }
 35 
 36 int strlen(char *str)
 37 {
 38     int i = 0;
 39     while (str[i])
 40     {
 41         i++;
 42     }
 43     return i;
 44 }
 45 
 46 void strcpy(char *dest, char *src)
 47 {
 48     while ((*dest++ = *src++) != '\0');
 49 }
 50 
 51 void setup_commandline_tag(char *cmdline)
 52 {
 53     int len = strlen(cmdline) + 1;
 54     
 55     params->hdr.tag  = ATAG_CMDLINE;
 56     params->hdr.size = (sizeof (struct tag_header) + len + 3) >> 2;
 57 
 58     strcpy (params->u.cmdline.cmdline, cmdline);
 59 
 60     params = tag_next (params);
 61 }
 62 
 63 void setup_end_tag(void)
 64 {
 65     params->hdr.tag = ATAG_NONE;
 66     params->hdr.size = 0;
 67 }
 68 
 69 
 70 int main(void)
 71 {
 72     void (*theKernel)(int zero, int arch, unsigned int params);
 73     volatile unsigned int *p = (volatile unsigned int *)0x30008000;
 74 
 75     /* 0. 帮内核设置串口: 内核启动的开始部分会从串口打印一些信息,但是内核一开始没有初始化串口 */
 76     uart0_init();
 77     
 78     /* 1. 从NAND FLASH里把内核读入内存 */
 79     puts("Copy kernel from nand\n\r");
 80     nand_read(0x60000+64, (unsigned char *)0x30008000, 0x200000);
 81     puthex(0x1234ABCD);
 82     puts("\n\r");
 83     puthex(*p);
 84     puts("\n\r");
 85 
 86     /* 2. 设置参数 */
 87     puts("Set boot params\n\r");
 88     setup_start_tag();
 89     setup_memory_tags();
 90     setup_commandline_tag("noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0");
 91     setup_end_tag();
 92 
 93     /* 3. 跳转执行 */
 94     puts("Boot kernel\n\r");
 95     theKernel = (void (*)(int, int, unsigned int))0x30008000;
 96     theKernel(0, 362, 0x30000100);  
 97     /* 
 98      *  mov r0, #0
 99      *  ldr r1, =362
100      *  ldr r2, =0x30000100
101      *  mov pc, #0x30008000 
102      */
103 
104     puts("Error!\n\r");
105     /* 如果一切正常, 不会执行到这里 */
106 
107     return -1;
108 }
复制代码

  3、对设备初始化部分(Nandflash、Uart等)

  

复制代码
  1 /* NAND FLASH控制器 */
  2 #define NFCONF (*((volatile unsigned long *)0x4E000000))
  3 #define NFCONT (*((volatile unsigned long *)0x4E000004))
  4 #define NFCMMD (*((volatile unsigned char *)0x4E000008))
  5 #define NFADDR (*((volatile unsigned char *)0x4E00000C))
  6 #define NFDATA (*((volatile unsigned char *)0x4E000010))
  7 #define NFSTAT (*((volatile unsigned char *)0x4E000020))
  8 
  9 /* GPIO */
 10 #define GPHCON              (*(volatile unsigned long *)0x56000070)
 11 #define GPHUP               (*(volatile unsigned long *)0x56000078)
 12 
 13 /* UART registers*/
 14 #define ULCON0              (*(volatile unsigned long *)0x50000000)
 15 #define UCON0               (*(volatile unsigned long *)0x50000004)
 16 #define UFCON0              (*(volatile unsigned long *)0x50000008)
 17 #define UMCON0              (*(volatile unsigned long *)0x5000000c)
 18 #define UTRSTAT0            (*(volatile unsigned long *)0x50000010)
 19 #define UTXH0               (*(volatile unsigned char *)0x50000020)
 20 #define URXH0               (*(volatile unsigned char *)0x50000024)
 21 #define UBRDIV0             (*(volatile unsigned long *)0x50000028)
 22 
 23 #define TXD0READY   (1<<2)
 24 
 25 
 26 void nand_read(unsigned int addr, unsigned char *buf, unsigned int len);
 27 
 28 
 29 int isBootFromNorFlash(void)
 30 {
 31     volatile int *p = (volatile int *)0;
 32     int val;
 33 
 34     val = *p;
 35     *p = 0x12345678;
 36     if (*p == 0x12345678)
 37     {
 38         /* 写成功, 是nand启动 */
 39         *p = val;
 40         return 0;
 41     }
 42     else
 43     {
 44         /* NOR不能像内存一样写 */
 45         return 1;
 46     }
 47 }
 48 
 49 void copy_code_to_sdram(unsigned char *src, unsigned char *dest, unsigned int len)
 50 {    
 51     int i = 0;
 52     
 53     /* 如果是NOR启动 */
 54     if (isBootFromNorFlash())
 55     {
 56         while (i < len)
 57         {
 58             dest[i] = src[i];
 59             i++;
 60         }
 61     }
 62     else
 63     {
 64         //nand_init();
 65         nand_read((unsigned int)src, dest, len);
 66     }
 67 }
 68 
 69 void clear_bss(void)
 70 {
 71     extern int __bss_start, __bss_end;
 72     int *p = &__bss_start;
 73     
 74     for (; p < &__bss_end; p++)
 75         *p = 0;
 76 }
 77 
 78 void nand_init(void)
 79 {
 80 #define TACLS   0
 81 #define TWRPH0  1
 82 #define TWRPH1  0
 83     /* 设置时序 */
 84     NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
 85     /* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
 86     NFCONT = (1<<4)|(1<<1)|(1<<0);    
 87 }
 88 
 89 void nand_select(void)
 90 {
 91     NFCONT &= ~(1<<1);    
 92 }
 93 
 94 void nand_deselect(void)
 95 {
 96     NFCONT |= (1<<1);    
 97 }
 98 
 99 void nand_cmd(unsigned char cmd)
100 {
101     volatile int i;
102     NFCMMD = cmd;
103     for (i = 0; i < 10; i++);
104 }
105 
106 void nand_addr(unsigned int addr)
107 {
108     unsigned int col  = addr % 2048;
109     unsigned int page = addr / 2048;
110     volatile int i;
111 
112     NFADDR = col & 0xff;
113     for (i = 0; i < 10; i++);
114     NFADDR = (col >> 8) & 0xff;
115     for (i = 0; i < 10; i++);
116     
117     NFADDR  = page & 0xff;
118     for (i = 0; i < 10; i++);
119     NFADDR  = (page >> 8) & 0xff;
120     for (i = 0; i < 10; i++);
121     NFADDR  = (page >> 16) & 0xff;
122     for (i = 0; i < 10; i++);    
123 }
124 
125 void nand_wait_ready(void)
126 {
127     while (!(NFSTAT & 1));
128 }
129 
130 unsigned char nand_data(void)
131 {
132     return NFDATA;
133 }
134 
135 void nand_read(unsigned int addr, unsigned char *buf, unsigned int len)
136 {
137     int col = addr % 2048;
138     int i = 0;
139         
140     /* 1. 选中 */
141     nand_select();
142 
143     while (i < len)
144     {
145         /* 2. 发出读命令00h */
146         nand_cmd(0x00);
147 
148         /* 3. 发出地址(分5步发出) */
149         nand_addr(addr);
150 
151         /* 4. 发出读命令30h */
152         nand_cmd(0x30);
153 
154         /* 5. 判断状态 */
155         nand_wait_ready();
156 
157         /* 6. 读数据 */
158         for (; (col < 2048) && (i < len); col++)
159         {
160             buf[i] = nand_data();
161             i++;
162             addr++;
163         }
164         
165         col = 0;
166     }
167 
168     /* 7. 取消选中 */        
169     nand_deselect();
170 }
171 
172 #define PCLK            50000000    // init.c中的clock_init函数设置PCLK为50MHz
173 #define UART_CLK        PCLK        //  UART0的时钟源设为PCLK
174 #define UART_BAUD_RATE  115200      // 波特率
175 #define UART_BRD        ((UART_CLK  / (UART_BAUD_RATE * 16)) - 1)
176 
177 /*
178  * 初始化UART0
179  * 115200,8N1,无流控
180  */
181 void uart0_init(void)
182 {
183     GPHCON  |= 0xa0;    // GPH2,GPH3用作TXD0,RXD0
184     GPHUP   = 0x0c;     // GPH2,GPH3内部上拉
185 
186     ULCON0  = 0x03;     // 8N1(8个数据位,无较验,1个停止位)
187     UCON0   = 0x05;     // 查询方式,UART时钟源为PCLK
188     UFCON0  = 0x00;     // 不使用FIFO
189     UMCON0  = 0x00;     // 不使用流控
190     UBRDIV0 = UART_BRD; // 波特率为115200
191 }
192 
193 /*
194  * 发送一个字符
195  */
196 void putc(unsigned char c)
197 {
198     /* 等待,直到发送缓冲区中的数据已经全部发送出去 */
199     while (!(UTRSTAT0 & TXD0READY));
200     
201     /* 向UTXH0寄存器中写入数据,UART即自动将它发送出去 */
202     UTXH0 = c;
203 }
204 
205 void puts(char *str)
206 {
207     int i = 0;
208     while (str[i])
209     {
210         putc(str[i]);
211         i++;
212     }
213 }
214 
215 void puthex(unsigned int val)
216 {
217     /* 0x1234abcd */
218     int i;
219     int j;
220     
221     puts("0x");
222 
223     for (i = 0; i < 8; i++)
224     {
225         j = (val >> ((7-i)*4)) & 0xf;
226         if ((j >= 0) && (j <= 9))
227             putc('0' + j);
228         else
229             putc('A' + j - 0xa);
230         
231     }
232     
233 }
复制代码

  4、寄存器地址设置、内核标记列表数据结构实现等

  

复制代码
  1 /*
  2  *  linux/include/asm/setup.h
  3  *
  4  *  Copyright (C) 1997-1999 Russell King
  5  *
  6  * This program is free software; you can redistribute it and/or modify
  7  * it under the terms of the GNU General Public License version 2 as
  8  * published by the Free Software Foundation.
  9  *
 10  *  Structure passed to kernel to tell it about the
 11  *  hardware it's running on.  See linux/Documentation/arm/Setup
 12  *  for more info.
 13  *
 14  * NOTE:
 15  *  This file contains two ways to pass information from the boot
 16  *  loader to the kernel. The old struct param_struct is deprecated,
 17  *  but it will be kept in the kernel for 5 years from now
 18  *  (2001). This will allow boot loaders to convert to the new struct
 19  *  tag way.
 20  */
 21 #ifndef __ASMARM_SETUP_H
 22 #define __ASMARM_SETUP_H
 23 
 24 #define u8  unsigned char
 25 #define u16 unsigned short
 26 #define u32 unsigned long
 27 
 28 /*
 29  * Usage:
 30  *  - do not go blindly adding fields, add them at the end
 31  *  - when adding fields, don't rely on the address until
 32  *    a patch from me has been released
 33  *  - unused fields should be zero (for future expansion)
 34  *  - this structure is relatively short-lived - only
 35  *    guaranteed to contain useful data in setup_arch()
 36  */
 37 #define COMMAND_LINE_SIZE 1024
 38 
 39 /* This is the old deprecated way to pass parameters to the kernel */
 40 struct param_struct {
 41     union {
 42     struct {
 43         unsigned long page_size;        /*  0 */
 44         unsigned long nr_pages;        /*  4 */
 45         unsigned long ramdisk_size;        /*  8 */
 46         unsigned long flags;        /* 12 */
 47 #define FLAG_READONLY    1
 48 #define FLAG_RDLOAD    4
 49 #define FLAG_RDPROMPT    8
 50         unsigned long rootdev;        /* 16 */
 51         unsigned long video_num_cols;    /* 20 */
 52         unsigned long video_num_rows;    /* 24 */
 53         unsigned long video_x;        /* 28 */
 54         unsigned long video_y;        /* 32 */
 55         unsigned long memc_control_reg;    /* 36 */
 56         unsigned char sounddefault;        /* 40 */
 57         unsigned char adfsdrives;        /* 41 */
 58         unsigned char bytes_per_char_h;    /* 42 */
 59         unsigned char bytes_per_char_v;    /* 43 */
 60         unsigned long pages_in_bank[4];    /* 44 */
 61         unsigned long pages_in_vram;    /* 60 */
 62         unsigned long initrd_start;        /* 64 */
 63         unsigned long initrd_size;        /* 68 */
 64         unsigned long rd_start;        /* 72 */
 65         unsigned long system_rev;        /* 76 */
 66         unsigned long system_serial_low;    /* 80 */
 67         unsigned long system_serial_high;    /* 84 */
 68         unsigned long mem_fclk_21285;       /* 88 */
 69     } s;
 70     char unused[256];
 71     } u1;
 72     union {
 73     char paths[8][128];
 74     struct {
 75         unsigned long magic;
 76         char n[1024 - sizeof(unsigned long)];
 77     } s;
 78     } u2;
 79     char commandline[COMMAND_LINE_SIZE];
 80 };
 81 
 82 
 83 /*
 84  * The new way of passing information: a list of tagged entries
 85  */
 86 
 87 /* The list ends with an ATAG_NONE node. */
 88 #define ATAG_NONE    0x00000000
 89 
 90 struct tag_header {
 91     u32 size;
 92     u32 tag;
 93 };
 94 
 95 /* The list must start with an ATAG_CORE node */
 96 #define ATAG_CORE    0x54410001
 97 
 98 struct tag_core {
 99     u32 flags;        /* bit 0 = read-only */
100     u32 pagesize;
101     u32 rootdev;
102 };
103 
104 /* it is allowed to have multiple ATAG_MEM nodes */
105 #define ATAG_MEM    0x54410002
106 
107 struct tag_mem32 {
108     u32    size;
109     u32    start;    /* physical start address */
110 };
111 
112 /* VGA text type displays */
113 #define ATAG_VIDEOTEXT    0x54410003
114 
115 struct tag_videotext {
116     u8        x;
117     u8        y;
118     u16        video_page;
119     u8        video_mode;
120     u8        video_cols;
121     u16        video_ega_bx;
122     u8        video_lines;
123     u8        video_isvga;
124     u16        video_points;
125 };
126 
127 /* describes how the ramdisk will be used in kernel */
128 #define ATAG_RAMDISK    0x54410004
129 
130 struct tag_ramdisk {
131     u32 flags;    /* bit 0 = load, bit 1 = prompt */
132     u32 size;    /* decompressed ramdisk size in _kilo_ bytes */
133     u32 start;    /* starting block of floppy-based RAM disk image */
134 };
135 
136 /* describes where the compressed ramdisk image lives (virtual address) */
137 /*
138  * this one accidentally used virtual addresses - as such,
139  * its depreciated.
140  */
141 #define ATAG_INITRD    0x54410005
142 
143 /* describes where the compressed ramdisk image lives (physical address) */
144 #define ATAG_INITRD2    0x54420005
145 
146 struct tag_initrd {
147     u32 start;    /* physical start address */
148     u32 size;    /* size of compressed ramdisk image in bytes */
149 };
150 
151 /* board serial number. "64 bits should be enough for everybody" */
152 #define ATAG_SERIAL    0x54410006
153 
154 struct tag_serialnr {
155     u32 low;
156     u32 high;
157 };
158 
159 /* board revision */
160 #define ATAG_REVISION    0x54410007
161 
162 struct tag_revision {
163     u32 rev;
164 };
165 
166 /* initial values for vesafb-type framebuffers. see struct screen_info
167  * in include/linux/tty.h
168  */
169 #define ATAG_VIDEOLFB    0x54410008
170 
171 struct tag_videolfb {
172     u16        lfb_width;
173     u16        lfb_height;
174     u16        lfb_depth;
175     u16        lfb_linelength;
176     u32        lfb_base;
177     u32        lfb_size;
178     u8        red_size;
179     u8        red_pos;
180     u8        green_size;
181     u8        green_pos;
182     u8        blue_size;
183     u8        blue_pos;
184     u8        rsvd_size;
185     u8        rsvd_pos;
186 };
187 
188 /* command line: \0 terminated string */
189 #define ATAG_CMDLINE    0x54410009
190 
191 struct tag_cmdline {
192     char    cmdline[1];    /* this is the minimum size */
193 };
194 
195 /* acorn RiscPC specific information */
196 #define ATAG_ACORN    0x41000101
197 
198 struct tag_acorn {
199     u32 memc_control_reg;
200     u32 vram_pages;
201     u8 sounddefault;
202     u8 adfsdrives;
203 };
204 
205 /* footbridge memory clock, see arch/arm/mach-footbridge/arch.c */
206 #define ATAG_MEMCLK    0x41000402
207 
208 struct tag_memclk {
209     u32 fmemclk;
210 };
211 
212 struct tag {
213     struct tag_header hdr;
214     union {
215         struct tag_core        core;
216         struct tag_mem32    mem;
217         struct tag_videotext    videotext;
218         struct tag_ramdisk    ramdisk;
219         struct tag_initrd    initrd;
220         struct tag_serialnr    serialnr;
221         struct tag_revision    revision;
222         struct tag_videolfb    videolfb;
223         struct tag_cmdline    cmdline;
224 
225         /*
226          * Acorn specific
227          */
228         struct tag_acorn    acorn;
229 
230         /*
231          * DC21285 specific
232          */
233         struct tag_memclk    memclk;
234     } u;
235 };
236 
237 struct tagtable {
238     u32 tag;
239     int (*parse)(const struct tag *);
240 };
241 
242 
243 #define tag_member_present(tag,member)                \
244     ((unsigned long)(&((struct tag *)0L)->member + 1)    \
245         <= (tag)->hdr.size * 4)
246 
247 #define tag_next(t)    ((struct tag *)((u32 *)(t) + (t)->hdr.size))
248 #define tag_size(type)    ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
249 
250 #define for_each_tag(t,base)        \
251     for (t = base; t->hdr.size; t = tag_next(t))
252 
253 /*
254  * Memory map description
255  */
256 #define NR_BANKS 8
257 
258 struct meminfo {
259     int nr_banks;
260     unsigned long end;
261     struct {
262         unsigned long start;
263         unsigned long size;
264         int           node;
265     } bank[NR_BANKS];
266 };
267 
268 extern struct meminfo meminfo;
269 
270 #endif
复制代码

 出处:https://www.cnblogs.com/qiuheng/p/5539241.html


相关教程