(linenum→info "unix/slp.c:2238")

qemu/0.9.1/hw/arm_boot.c

    1: /*
    2:  * ARM kernel loader.
    3:  *
    4:  * Copyright (c) 2006-2007 CodeSourcery.
    5:  * Written by Paul Brook
    6:  *
    7:  * This code is licenced under the GPL.
    8:  */
    9: 
   10: #include "hw.h"
   11: #include "arm-misc.h"
   12: #include "sysemu.h"
   13: 
   14: #define KERNEL_ARGS_ADDR 0x100
   15: #define KERNEL_LOAD_ADDR 0x00010000
   16: #define INITRD_LOAD_ADDR 0x00800000
   17: 
   18: /* The worlds second smallest bootloader.  Set r0-r2, then jump to kernel.  */
   19: static uint32_t bootloader[] = {
   20:   0xe3a00000, /* mov     r0, #0 */
   21:   0xe3a01000, /* mov     r1, #0x?? */
   22:   0xe3811c00, /* orr     r1, r1, #0x??00 */
   23:   0xe59f2000, /* ldr     r2, [pc, #0] */
   24:   0xe59ff000, /* ldr     pc, [pc, #0] */
   25:   0, /* Address of kernel args.  Set by integratorcp_init.  */
   26:   0  /* Kernel entry point.  Set by integratorcp_init.  */
   27: };
   28: 
   29: /* Entry point for secondary CPUs.  Enable interrupt controller and
   30:    Issue WFI until start address is written to system controller.  */
   31: static uint32_t smpboot[] = {
   32:   0xe3a00201, /* mov     r0, #0x10000000 */
   33:   0xe3800601, /* orr     r0, r0, #0x001000000 */
   34:   0xe3a01001, /* mov     r1, #1 */
   35:   0xe5801100, /* str     r1, [r0, #0x100] */
   36:   0xe3a00201, /* mov     r0, #0x10000000 */
   37:   0xe3800030, /* orr     r0, #0x30 */
   38:   0xe320f003, /* wfi */
   39:   0xe5901000, /* ldr     r1, [r0] */
   40:   0xe3110003, /* tst     r1, #3 */
   41:   0x1afffffb, /* bne     <wfi> */
   42:   0xe12fff11  /* bx      r1 */
   43: };
   44: 
   45: static void main_cpu_reset(void *opaque)
   46: {
   47:     CPUState *env = opaque;
   48: 
   49:     cpu_reset(env);
   50:     if (env->kernel_filename)
   51:         arm_load_kernel(env, env->ram_size, env->kernel_filename,
   52:                         env->kernel_cmdline, env->initrd_filename,
   53:                         env->board_id, env->loader_start);
   54: 
   55:     /* TODO:  Reset secondary CPUs.  */
   56: }
   57: 
   58: static void set_kernel_args(uint32_t ram_size, int initrd_size,
   59:                             const char *kernel_cmdline,
   60:                             target_phys_addr_t loader_start)
   61: {
   62:     uint32_t *p;
   63: 
   64:     p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR);
   65:     /* ATAG_CORE */
   66:     stl_raw(p++, 5);
   67:     stl_raw(p++, 0x54410001);
   68:     stl_raw(p++, 1);
   69:     stl_raw(p++, 0x1000);
   70:     stl_raw(p++, 0);
   71:     /* ATAG_MEM */
   72:     stl_raw(p++, 4);
   73:     stl_raw(p++, 0x54410002);
   74:     stl_raw(p++, ram_size);
   75:     stl_raw(p++, loader_start);
   76:     if (initrd_size) {
   77:         /* ATAG_INITRD2 */
   78:         stl_raw(p++, 4);
   79:         stl_raw(p++, 0x54420005);
   80:         stl_raw(p++, loader_start + INITRD_LOAD_ADDR);
   81:         stl_raw(p++, initrd_size);
   82:     }
   83:     if (kernel_cmdline && *kernel_cmdline) {
   84:         /* ATAG_CMDLINE */
   85:         int cmdline_size;
   86: 
   87:         cmdline_size = strlen(kernel_cmdline);
   88:         memcpy (p + 2, kernel_cmdline, cmdline_size + 1);
   89:         cmdline_size = (cmdline_size >> 2) + 1;
   90:         stl_raw(p++, cmdline_size + 2);
   91:         stl_raw(p++, 0x54410009);
   92:         p += cmdline_size;
   93:     }
   94:     /* ATAG_END */
   95:     stl_raw(p++, 0);
   96:     stl_raw(p++, 0);
   97: }
   98: 
   99: static void set_kernel_args_old(uint32_t ram_size, int initrd_size,
  100:                                 const char *kernel_cmdline,
  101:                                 target_phys_addr_t loader_start)
  102: {
  103:     uint32_t *p;
  104:     unsigned char *s;
  105: 
  106:     /* see linux/include/asm-arm/setup.h */
  107:     p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR);
  108:     /* page_size */
  109:     stl_raw(p++, 4096);
  110:     /* nr_pages */
  111:     stl_raw(p++, ram_size / 4096);
  112:     /* ramdisk_size */
  113:     stl_raw(p++, 0);
  114: #define FLAG_READONLY   1
  115: #define FLAG_RDLOAD     4
  116: #define FLAG_RDPROMPT   8
  117:     /* flags */
  118:     stl_raw(p++, FLAG_READONLY | FLAG_RDLOAD | FLAG_RDPROMPT);
  119:     /* rootdev */
  120:     stl_raw(p++, (31 << 8) | 0);        /* /dev/mtdblock0 */
  121:     /* video_num_cols */
  122:     stl_raw(p++, 0);
  123:     /* video_num_rows */
  124:     stl_raw(p++, 0);
  125:     /* video_x */
  126:     stl_raw(p++, 0);
  127:     /* video_y */
  128:     stl_raw(p++, 0);
  129:     /* memc_control_reg */
  130:     stl_raw(p++, 0);
  131:     /* unsigned char sounddefault */
  132:     /* unsigned char adfsdrives */
  133:     /* unsigned char bytes_per_char_h */
  134:     /* unsigned char bytes_per_char_v */
  135:     stl_raw(p++, 0);
  136:     /* pages_in_bank[4] */
  137:     stl_raw(p++, 0);
  138:     stl_raw(p++, 0);
  139:     stl_raw(p++, 0);
  140:     stl_raw(p++, 0);
  141:     /* pages_in_vram */
  142:     stl_raw(p++, 0);
  143:     /* initrd_start */
  144:     if (initrd_size)
  145:         stl_raw(p++, loader_start + INITRD_LOAD_ADDR);
  146:     else
  147:         stl_raw(p++, 0);
  148:     /* initrd_size */
  149:     stl_raw(p++, initrd_size);
  150:     /* rd_start */
  151:     stl_raw(p++, 0);
  152:     /* system_rev */
  153:     stl_raw(p++, 0);
  154:     /* system_serial_low */
  155:     stl_raw(p++, 0);
  156:     /* system_serial_high */
  157:     stl_raw(p++, 0);
  158:     /* mem_fclk_21285 */
  159:     stl_raw(p++, 0);
  160:     /* zero unused fields */
  161:     memset(p, 0, 256 + 1024 -
  162:            (p - ((uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR))));
  163:     s = phys_ram_base + KERNEL_ARGS_ADDR + 256 + 1024;
  164:     if (kernel_cmdline)
  165:         strcpy (s, kernel_cmdline);
  166:     else
  167:         stb_raw(s, 0);
  168: }
  169: 
  170: void arm_load_kernel(CPUState *env, int ram_size, const char *kernel_filename,
  171:                      const char *kernel_cmdline, const char *initrd_filename,
  172:                      int board_id, target_phys_addr_t loader_start)
  173: {
  174:     int kernel_size;
  175:     int initrd_size;
  176:     int n;
  177:     int is_linux = 0;
  178:     uint64_t elf_entry;
  179:     target_ulong entry;
  180: 
  181:     /* Load the kernel.  */
  182:     if (!kernel_filename) {
  183:         fprintf(stderr, "Kernel image must be specified\n");
  184:         exit(1);
  185:     }
  186: 
  187:     if (!env->kernel_filename) {
  188:         env->ram_size = ram_size;
  189:         env->kernel_filename = kernel_filename;
  190:         env->kernel_cmdline = kernel_cmdline;
  191:         env->initrd_filename = initrd_filename;
  192:         env->board_id = board_id;
  193:         env->loader_start = loader_start;
  194:         qemu_register_reset(main_cpu_reset, env);
  195:     }
  196:     /* Assume that raw images are linux kernels, and ELF images are not.  */
  197:     kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL);
  198:     entry = elf_entry;
  199:     if (kernel_size < 0) {
  200:         kernel_size = load_uboot(kernel_filename, &entry, &is_linux);
  201:     }
  202:     if (kernel_size < 0) {
  203:         kernel_size = load_image(kernel_filename,
  204:                                  phys_ram_base + KERNEL_LOAD_ADDR);
  205:         entry = loader_start + KERNEL_LOAD_ADDR;
  206:         is_linux = 1;
  207:     }
  208:     if (kernel_size < 0) {
  209:         fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
  210:         exit(1);
  211:     }
  212:     if (!is_linux) {
  213:         /* Jump to the entry point.  */
  214:         env->regs[15] = entry & 0xfffffffe;
  215:         env->thumb = entry & 1;
  216:     } else {
  217:         if (initrd_filename) {
  218:             initrd_size = load_image(initrd_filename,
  219:                                      phys_ram_base + INITRD_LOAD_ADDR);
  220:             if (initrd_size < 0) {
  221:                 fprintf(stderr, "qemu: could not load initrd '%s'\n",
  222:                         initrd_filename);
  223:                 exit(1);
  224:             }
  225:         } else {
  226:             initrd_size = 0;
  227:         }
  228:         bootloader[1] |= board_id & 0xff;
  229:         bootloader[2] |= (board_id >> 8) & 0xff;
  230:         bootloader[5] = loader_start + KERNEL_ARGS_ADDR;
  231:         bootloader[6] = entry;
  232:         for (n = 0; n < sizeof(bootloader) / 4; n++)
  233:             stl_raw(phys_ram_base + (n * 4), bootloader[n]);
  234:         for (n = 0; n < sizeof(smpboot) / 4; n++)
  235:             stl_raw(phys_ram_base + ram_size + (n * 4), smpboot[n]);
  236:         if (old_param)
  237:             set_kernel_args_old(ram_size, initrd_size,
  238:                                 kernel_cmdline, loader_start);
  239:         else
  240:             set_kernel_args(ram_size, initrd_size,
  241:                             kernel_cmdline, loader_start);
  242:     }
  243: }
Syntax (Markdown)