fw-emu.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:14k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * PAL & SAL emulation.
  3.  *
  4.  * Copyright (C) 1998-2001 Hewlett-Packard Co
  5.  * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  6.  *
  7.  * For the HP simulator, this file gets include in boot/bootloader.c.
  8.  * For SoftSDV, this file gets included in sys_softsdv.c.
  9.  */
  10. #include <linux/config.h>
  11. #ifdef CONFIG_PCI
  12. # include <linux/pci.h>
  13. #endif
  14. #include <linux/efi.h>
  15. #include <asm/io.h>
  16. #include <asm/pal.h>
  17. #include <asm/sal.h>
  18. #define MB (1024*1024UL)
  19. #define GB (1024*MB)
  20. #define TB (1024*GB)
  21. #define NUM_MEM_DESCS 4
  22. static char fw_mem[(  sizeof(struct ia64_boot_param)
  23.     + sizeof(efi_system_table_t)
  24.     + sizeof(efi_runtime_services_t)
  25.     + 1*sizeof(efi_config_table_t)
  26.     + sizeof(struct ia64_sal_systab)
  27.     + sizeof(struct ia64_sal_desc_entry_point)
  28.     + NUM_MEM_DESCS*(sizeof(efi_memory_desc_t))
  29.     + 1024)] __attribute__ ((aligned (8)));
  30. #ifdef CONFIG_IA64_HP_SIM
  31. /* Simulator system calls: */
  32. #define SSC_EXIT 66
  33. /*
  34.  * Simulator system call.
  35.  */
  36. static long
  37. ssc (long arg0, long arg1, long arg2, long arg3, int nr)
  38. {
  39. register long r8 asm ("r8");
  40. asm volatile ("mov r15=%1nt"
  41.       "break 0x80001"
  42.       : "=r"(r8)
  43.       : "r"(nr), "r"(arg0), "r"(arg1), "r"(arg2), "r"(arg3));
  44. return r8;
  45. }
  46. #define SECS_PER_HOUR   (60 * 60)
  47. #define SECS_PER_DAY    (SECS_PER_HOUR * 24)
  48. /* Compute the `struct tm' representation of *T,
  49.    offset OFFSET seconds east of UTC,
  50.    and store year, yday, mon, mday, wday, hour, min, sec into *TP.
  51.    Return nonzero if successful.  */
  52. int
  53. offtime (unsigned long t, efi_time_t *tp)
  54. {
  55. const unsigned short int __mon_yday[2][13] =
  56. {
  57. /* Normal years.  */
  58. { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
  59. /* Leap years.  */
  60. { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
  61. };
  62. long int days, rem, y;
  63. const unsigned short int *ip;
  64. days = t / SECS_PER_DAY;
  65. rem = t % SECS_PER_DAY;
  66. while (rem < 0) {
  67. rem += SECS_PER_DAY;
  68. --days;
  69. }
  70. while (rem >= SECS_PER_DAY) {
  71. rem -= SECS_PER_DAY;
  72. ++days;
  73. }
  74. tp->hour = rem / SECS_PER_HOUR;
  75. rem %= SECS_PER_HOUR;
  76. tp->minute = rem / 60;
  77. tp->second = rem % 60;
  78. /* January 1, 1970 was a Thursday.  */
  79. y = 1970;
  80. # define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
  81. # define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
  82. # define __isleap(year) 
  83.   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
  84. while (days < 0 || days >= (__isleap (y) ? 366 : 365)) {
  85. /* Guess a corrected year, assuming 365 days per year.  */
  86. long int yg = y + days / 365 - (days % 365 < 0);
  87. /* Adjust DAYS and Y to match the guessed year.  */
  88. days -= ((yg - y) * 365 + LEAPS_THRU_END_OF (yg - 1)
  89.  - LEAPS_THRU_END_OF (y - 1));
  90. y = yg;
  91. }
  92. tp->year = y;
  93. ip = __mon_yday[__isleap(y)];
  94. for (y = 11; days < (long int) ip[y]; --y)
  95. continue;
  96. days -= ip[y];
  97. tp->month = y + 1;
  98. tp->day = days + 1;
  99. return 1;
  100. }
  101. #endif /* CONFIG_IA64_HP_SIM */
  102. /*
  103.  * Very ugly, but we need this in the simulator only.  Once we run on
  104.  * real hw, this can all go away.
  105.  */
  106. extern void pal_emulator_static (void);
  107. asm (
  108. " .proc pal_emulator_staticn"
  109. "pal_emulator_static:"
  110. " mov r8=-1n"
  111. " mov r9=256n"
  112. " ;;n"
  113. " cmp.gtu p6,p7=r9,r28 /* r28 <= 255? */n"
  114. "(p6) br.cond.sptk.few staticn"
  115. " ;;n"
  116. " mov r9=512n"
  117. " ;;n"
  118. " cmp.gtu p6,p7=r9,r28n"
  119. "(p6) br.cond.sptk.few stackedn"
  120. " ;;n"
  121. "static: cmp.eq p6,p7=6,r28 /* PAL_PTCE_INFO */n"
  122. "(p7) br.cond.sptk.few 1fn"
  123. " ;;n"
  124. " mov r8=0 /* status = 0 */n"
  125. " movl r9=0x100000000 /* tc.base */n"
  126. " movl r10=0x0000000200000003 /* count[0], count[1] */n"
  127. " movl r11=0x1000000000002000 /* stride[0], stride[1] */n"
  128. " br.cond.sptk.few rpn"
  129. "1: cmp.eq p6,p7=14,r28 /* PAL_FREQ_RATIOS */n"
  130. "(p7) br.cond.sptk.few 1fn"
  131. " mov r8=0 /* status = 0 */n"
  132. " movl r9 =0x100000064 /* proc_ratio (1/100) */n"
  133. " movl r10=0x100000100 /* bus_ratio<<32 (1/256) */n"
  134. " movl r11=0x100000064 /* itc_ratio<<32 (1/100) */n"
  135. " ;;n"
  136. "1: cmp.eq p6,p7=19,r28 /* PAL_RSE_INFO */n"
  137. "(p7) br.cond.sptk.few 1fn"
  138. " mov r8=0 /* status = 0 */n"
  139. " mov r9=96 /* num phys stacked */n"
  140. " mov r10=0 /* hints */n"
  141. " mov r11=0n"
  142. " br.cond.sptk.few rpn"
  143. "1: cmp.eq p6,p7=1,r28 /* PAL_CACHE_FLUSH */n"
  144. "(p7) br.cond.sptk.few 1fn"
  145. " mov r9=ar.lcn"
  146. " movl r8=524288 /* flush 512k million cache lines (16MB) */n"
  147. " ;;n"
  148. " mov ar.lc=r8n"
  149. " movl r8=0xe000000000000000n"
  150. " ;;n"
  151. ".loop: fc r8n"
  152. " add r8=32,r8n"
  153. " br.cloop.sptk.few .loopn"
  154. " sync.in"
  155. " ;;n"
  156. " srlz.in"
  157. " ;;n"
  158. " mov ar.lc=r9n"
  159. " mov r8=r0n"
  160. " ;;n"
  161. "1: cmp.eq p6,p7=15,r28 /* PAL_PERF_MON_INFO */n"
  162. "(p7) br.cond.sptk.few 1fn"
  163. " mov r8=0 /* status = 0 */n"
  164. " movl r9 =0x12082004 /* generic=4 width=32 retired=8 cycles=18 */n"
  165. " mov r10=0 /* reserved */n"
  166. " mov r11=0 /* reserved */n"
  167. " mov r16=0xffff /* implemented PMC */n"
  168. " mov r17=0xffff /* implemented PMD */n"
  169. " add r18=8,r29 /* second index */n"
  170. " ;;n"
  171. " st8 [r29]=r16,16 /* store implemented PMC */n"
  172. " st8 [r18]=r0,16 /* clear remaining bits  */n"
  173. " ;;n"
  174. " st8 [r29]=r0,16 /* store implemented PMC */n"
  175. " st8 [r18]=r0,16 /* clear remaining bits  */n"
  176. " ;;n"
  177. " st8 [r29]=r17,16 /* store implemented PMD */n"
  178. " st8 [r18]=r0,16 /* clear remaining bits  */n"
  179. " mov r16=0xf0 /* cycles count capable PMC */n"
  180. " ;;n"
  181. " st8 [r29]=r0,16 /* store implemented PMC */n"
  182. " st8 [r18]=r0,16 /* clear remaining bits  */n"
  183. " mov r17=0x10 /* retired bundles capable PMC */n"
  184. " ;;n"
  185. " st8 [r29]=r16,16 /* store cycles capable */n"
  186. " st8 [r18]=r0,16 /* clear remaining bits  */n"
  187. " ;;n"
  188. " st8 [r29]=r0,16 /* store implemented PMC */n"
  189. " st8 [r18]=r0,16 /* clear remaining bits  */n"
  190. " ;;n"
  191. " st8 [r29]=r17,16 /* store retired bundle capable */n"
  192. " st8 [r18]=r0,16 /* clear remaining bits  */n"
  193. " ;;n"
  194. " st8 [r29]=r0,16 /* store implemented PMC */n"
  195. " st8 [r18]=r0,16 /* clear remaining bits  */n"
  196. " ;;n"
  197. "1: br.cond.sptk.few rpn"
  198. "stacked:n"
  199. " br.ret.sptk.few rpn"
  200. " .endp pal_emulator_staticn");
  201. /* Macro to emulate SAL call using legacy IN and OUT calls to CF8, CFC etc.. */
  202. #define BUILD_CMD(addr) ((0x80000000 | (addr)) & ~3)
  203. #define REG_OFFSET(addr) (0x00000000000000FF & (addr))
  204. #define DEVICE_FUNCTION(addr) (0x000000000000FF00 & (addr))
  205. #define BUS_NUMBER(addr) (0x0000000000FF0000 & (addr))
  206. static efi_status_t
  207. efi_get_time (efi_time_t *tm, efi_time_cap_t *tc)
  208. {
  209. #ifdef CONFIG_IA64_HP_SIM
  210. struct {
  211. int tv_sec; /* must be 32bits to work */
  212. int tv_usec;
  213. } tv32bits;
  214. ssc((unsigned long) &tv32bits, 0, 0, 0, SSC_GET_TOD);
  215. memset(tm, 0, sizeof(*tm));
  216. offtime(tv32bits.tv_sec, tm);
  217. if (tc)
  218. memset(tc, 0, sizeof(*tc));
  219. #else
  220. # error Not implemented yet...
  221. #endif
  222. return EFI_SUCCESS;
  223. }
  224. static void
  225. efi_reset_system (int reset_type, efi_status_t status, unsigned long data_size, efi_char16_t *data)
  226. {
  227. #ifdef CONFIG_IA64_HP_SIM
  228. ssc(status, 0, 0, 0, SSC_EXIT);
  229. #else
  230. # error Not implemented yet...
  231. #endif
  232. }
  233. static efi_status_t
  234. efi_unimplemented (void)
  235. {
  236. return EFI_UNSUPPORTED;
  237. }
  238. static long
  239. sal_emulator (long index, unsigned long in1, unsigned long in2,
  240.       unsigned long in3, unsigned long in4, unsigned long in5,
  241.       unsigned long in6, unsigned long in7)
  242. {
  243. register long r9 asm ("r9") = 0;
  244. register long r10 asm ("r10") = 0;
  245. register long r11 asm ("r11") = 0;
  246. long status;
  247. /*
  248.  * Don't do a "switch" here since that gives us code that
  249.  * isn't self-relocatable.
  250.  */
  251. status = 0;
  252. if (index == SAL_FREQ_BASE) {
  253. switch (in1) {
  254.       case SAL_FREQ_BASE_PLATFORM:
  255. r9 = 200000000;
  256. break;
  257.       case SAL_FREQ_BASE_INTERVAL_TIMER:
  258. /*
  259.  * Is this supposed to be the cr.itc frequency
  260.  * or something platform specific?  The SAL
  261.  * doc ain't exactly clear on this...
  262.  */
  263. r9 = 700000000;
  264. break;
  265.       case SAL_FREQ_BASE_REALTIME_CLOCK:
  266. r9 = 1;
  267. break;
  268.       default:
  269. status = -1;
  270. break;
  271. }
  272. } else if (index == SAL_SET_VECTORS) {
  273. ;
  274. } else if (index == SAL_GET_STATE_INFO) {
  275. ;
  276. } else if (index == SAL_GET_STATE_INFO_SIZE) {
  277. ;
  278. } else if (index == SAL_CLEAR_STATE_INFO) {
  279. ;
  280. } else if (index == SAL_MC_RENDEZ) {
  281. ;
  282. } else if (index == SAL_MC_SET_PARAMS) {
  283. ;
  284. } else if (index == SAL_CACHE_FLUSH) {
  285. ;
  286. } else if (index == SAL_CACHE_INIT) {
  287. ;
  288. #ifdef CONFIG_PCI
  289. } else if (index == SAL_PCI_CONFIG_READ) {
  290. /*
  291.  * in1 contains the PCI configuration address and in2
  292.  * the size of the read.  The value that is read is
  293.  * returned via the general register r9.
  294.  */
  295.                 outl(BUILD_CMD(in1), 0xCF8);
  296.                 if (in2 == 1)                           /* Reading byte  */
  297.                         r9 = inb(0xCFC + ((REG_OFFSET(in1) & 3)));
  298.                 else if (in2 == 2)                      /* Reading word  */
  299.                         r9 = inw(0xCFC + ((REG_OFFSET(in1) & 2)));
  300.                 else                                    /* Reading dword */
  301.                         r9 = inl(0xCFC);
  302.                 status = PCIBIOS_SUCCESSFUL;
  303. } else if (index == SAL_PCI_CONFIG_WRITE) {
  304.        /*
  305.  * in1 contains the PCI configuration address, in2 the
  306.  * size of the write, and in3 the actual value to be
  307.  * written out.
  308.  */
  309.                 outl(BUILD_CMD(in1), 0xCF8);
  310.                 if (in2 == 1)                           /* Writing byte  */
  311.                         outb(in3, 0xCFC + ((REG_OFFSET(in1) & 3)));
  312.                 else if (in2 == 2)                      /* Writing word  */
  313.                         outw(in3, 0xCFC + ((REG_OFFSET(in1) & 2)));
  314.                 else                                    /* Writing dword */
  315.                         outl(in3, 0xCFC);
  316.                 status = PCIBIOS_SUCCESSFUL;
  317. #endif /* CONFIG_PCI */
  318. } else if (index == SAL_UPDATE_PAL) {
  319. ;
  320. } else {
  321. status = -1;
  322. }
  323. asm volatile ("" :: "r"(r9), "r"(r10), "r"(r11));
  324. return status;
  325. }
  326. /*
  327.  * This is here to work around a bug in egcs-1.1.1b that causes the
  328.  * compiler to crash (seems like a bug in the new alias analysis code.
  329.  */
  330. void *
  331. id (long addr)
  332. {
  333. return (void *) addr;
  334. }
  335. struct ia64_boot_param *
  336. sys_fw_init (const char *args, int arglen)
  337. {
  338. efi_system_table_t *efi_systab;
  339. efi_runtime_services_t *efi_runtime;
  340. efi_config_table_t *efi_tables;
  341. struct ia64_sal_systab *sal_systab;
  342. efi_memory_desc_t *efi_memmap, *md;
  343. unsigned long *pal_desc, *sal_desc;
  344. struct ia64_sal_desc_entry_point *sal_ed;
  345. struct ia64_boot_param *bp;
  346. unsigned char checksum = 0;
  347. char *cp, *cmd_line;
  348. memset(fw_mem, 0, sizeof(fw_mem));
  349. pal_desc = (unsigned long *) &pal_emulator_static;
  350. sal_desc = (unsigned long *) &sal_emulator;
  351. cp = fw_mem;
  352. efi_systab  = (void *) cp; cp += sizeof(*efi_systab);
  353. efi_runtime = (void *) cp; cp += sizeof(*efi_runtime);
  354. efi_tables  = (void *) cp; cp += sizeof(*efi_tables);
  355. sal_systab  = (void *) cp; cp += sizeof(*sal_systab);
  356. sal_ed      = (void *) cp; cp += sizeof(*sal_ed);
  357. efi_memmap  = (void *) cp; cp += NUM_MEM_DESCS*sizeof(*efi_memmap);
  358. bp     = (void *) cp; cp += sizeof(*bp);
  359. cmd_line    = (void *) cp;
  360. if (args) {
  361. if (arglen >= 1024)
  362. arglen = 1023;
  363. memcpy(cmd_line, args, arglen);
  364. } else {
  365. arglen = 0;
  366. }
  367. cmd_line[arglen] = '';
  368. memset(efi_systab, 0, sizeof(efi_systab));
  369. efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
  370. efi_systab->hdr.revision  = EFI_SYSTEM_TABLE_REVISION;
  371. efi_systab->hdr.headersize = sizeof(efi_systab->hdr);
  372. efi_systab->fw_vendor = __pa("Hewlett-Packard");
  373. efi_systab->fw_revision = 1;
  374. efi_systab->runtime = __pa(efi_runtime);
  375. efi_systab->nr_tables = 1;
  376. efi_systab->tables = __pa(efi_tables);
  377. efi_runtime->hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE;
  378. efi_runtime->hdr.revision = EFI_RUNTIME_SERVICES_REVISION;
  379. efi_runtime->hdr.headersize = sizeof(efi_runtime->hdr);
  380. efi_runtime->get_time = __pa(&efi_get_time);
  381. efi_runtime->set_time = __pa(&efi_unimplemented);
  382. efi_runtime->get_wakeup_time = __pa(&efi_unimplemented);
  383. efi_runtime->set_wakeup_time = __pa(&efi_unimplemented);
  384. efi_runtime->set_virtual_address_map = __pa(&efi_unimplemented);
  385. efi_runtime->get_variable = __pa(&efi_unimplemented);
  386. efi_runtime->get_next_variable = __pa(&efi_unimplemented);
  387. efi_runtime->set_variable = __pa(&efi_unimplemented);
  388. efi_runtime->get_next_high_mono_count = __pa(&efi_unimplemented);
  389. efi_runtime->reset_system = __pa(&efi_reset_system);
  390. efi_tables->guid = SAL_SYSTEM_TABLE_GUID;
  391. efi_tables->table = __pa(sal_systab);
  392. /* fill in the SAL system table: */
  393. memcpy(sal_systab->signature, "SST_", 4);
  394. sal_systab->size = sizeof(*sal_systab);
  395. sal_systab->sal_rev_minor = 1;
  396. sal_systab->sal_rev_major = 0;
  397. sal_systab->entry_count = 1;
  398. #ifdef CONFIG_IA64_GENERIC
  399.         strcpy(sal_systab->oem_id, "Generic");
  400.         strcpy(sal_systab->product_id, "IA-64 system");
  401. #endif
  402. #ifdef CONFIG_IA64_HP_SIM
  403. strcpy(sal_systab->oem_id, "Hewlett-Packard");
  404. strcpy(sal_systab->product_id, "HP-simulator");
  405. #endif
  406. #ifdef CONFIG_IA64_SDV
  407. strcpy(sal_systab->oem_id, "Intel");
  408. strcpy(sal_systab->product_id, "SDV");
  409. #endif
  410. /* fill in an entry point: */
  411. sal_ed->type = SAL_DESC_ENTRY_POINT;
  412. sal_ed->pal_proc = __pa(pal_desc[0]);
  413. sal_ed->sal_proc = __pa(sal_desc[0]);
  414. sal_ed->gp = __pa(sal_desc[1]);
  415. for (cp = (char *) sal_systab; cp < (char *) efi_memmap; ++cp)
  416. checksum += *cp;
  417. sal_systab->checksum = -checksum;
  418. /* simulate free memory at physical address zero */
  419. md = &efi_memmap[0];
  420. md->type = EFI_BOOT_SERVICES_DATA;
  421. md->pad = 0;
  422. md->phys_addr = 0*MB;
  423. md->virt_addr = 0;
  424. md->num_pages = (1*MB) >> 12; /* 1MB (in 4KB pages) */
  425. md->attribute = EFI_MEMORY_WB | EFI_MEMORY_WC | EFI_MEMORY_UC;
  426. /* fill in a memory descriptor: */
  427. md = &efi_memmap[1];
  428. md->type = EFI_CONVENTIONAL_MEMORY;
  429. md->pad = 0;
  430. md->phys_addr = 2*MB;
  431. md->virt_addr = 0;
  432. md->num_pages = (128*MB) >> 12; /* 128MB (in 4KB pages) */
  433. md->attribute = EFI_MEMORY_WB;
  434. /* descriptor for firmware emulator: */
  435. md = &efi_memmap[2];
  436. md->type = EFI_PAL_CODE;
  437. md->pad = 0;
  438. md->phys_addr = 1*MB;
  439. md->virt_addr = 1*MB;
  440. md->num_pages = (1*MB) >> 12; /* 1MB (in 4KB pages) */
  441. md->attribute = EFI_MEMORY_WB | EFI_MEMORY_WC | EFI_MEMORY_UC;
  442. /* descriptor for high memory (>4TB): */
  443. md = &efi_memmap[3];
  444. md->type = EFI_CONVENTIONAL_MEMORY;
  445. md->pad = 0;
  446. md->phys_addr = 4*TB;
  447. md->virt_addr = 0;
  448. md->num_pages = (64*MB) >> 12; /* 64MB (in 4KB pages) */
  449. md->attribute = EFI_MEMORY_WB;
  450. bp->efi_systab = __pa(&fw_mem);
  451. bp->efi_memmap = __pa(efi_memmap);
  452. bp->efi_memmap_size = NUM_MEM_DESCS*sizeof(efi_memory_desc_t);
  453. bp->efi_memdesc_size = sizeof(efi_memory_desc_t);
  454. bp->efi_memdesc_version = 1;
  455. bp->command_line = __pa(cmd_line);
  456. bp->console_info.num_cols = 80;
  457. bp->console_info.num_rows = 25;
  458. bp->console_info.orig_x = 0;
  459. bp->console_info.orig_y = 24;
  460. bp->fpswa = 0;
  461. return bp;
  462. }