4 * Copyright (C) 1998-2001 Hewlett-Packard Co
5 * David Mosberger-Tang <davidm@hpl.hp.com>
7 * For the HP simulator, this file gets include in boot/bootloader.c.
8 * For SoftSDV, this file gets included in sys_softsdv.c.
10 #include <linux/config.h>
13 # include <linux/pci.h>
16 #include <linux/efi.h>
21 #define MB (1024*1024UL)
23 #define SIMPLE_MEMMAP 1
26 # define NUM_MEM_DESCS 4
28 # define NUM_MEM_DESCS 16
31 static char fw_mem[( sizeof(struct ia64_boot_param)
32 + sizeof(efi_system_table_t)
33 + sizeof(efi_runtime_services_t)
34 + 1*sizeof(efi_config_table_t)
35 + sizeof(struct ia64_sal_systab)
36 + sizeof(struct ia64_sal_desc_entry_point)
37 + NUM_MEM_DESCS*(sizeof(efi_memory_desc_t))
38 + 1024)] __attribute__ ((aligned (8)));
40 #if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC)
42 /* Simulator system calls: */
47 * Simulator system call.
50 ssc (long arg0, long arg1, long arg2, long arg3, int nr)
52 register long r8 asm ("r8");
54 asm volatile ("mov r15=%1\n\t"
57 : "r"(nr), "r"(arg0), "r"(arg1), "r"(arg2), "r"(arg3));
61 #define SECS_PER_HOUR (60 * 60)
62 #define SECS_PER_DAY (SECS_PER_HOUR * 24)
64 /* Compute the `struct tm' representation of *T,
65 offset OFFSET seconds east of UTC,
66 and store year, yday, mon, mday, wday, hour, min, sec into *TP.
67 Return nonzero if successful. */
69 offtime (unsigned long t, efi_time_t *tp)
71 const unsigned short int __mon_yday[2][13] =
74 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
76 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
78 long int days, rem, y;
79 const unsigned short int *ip;
81 days = t / SECS_PER_DAY;
82 rem = t % SECS_PER_DAY;
87 while (rem >= SECS_PER_DAY) {
91 tp->hour = rem / SECS_PER_HOUR;
93 tp->minute = rem / 60;
94 tp->second = rem % 60;
95 /* January 1, 1970 was a Thursday. */
98 # define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
99 # define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
100 # define __isleap(year) \
101 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
103 while (days < 0 || days >= (__isleap (y) ? 366 : 365)) {
104 /* Guess a corrected year, assuming 365 days per year. */
105 long int yg = y + days / 365 - (days % 365 < 0);
107 /* Adjust DAYS and Y to match the guessed year. */
108 days -= ((yg - y) * 365 + LEAPS_THRU_END_OF (yg - 1)
109 - LEAPS_THRU_END_OF (y - 1));
113 ip = __mon_yday[__isleap(y)];
114 for (y = 11; days < (long int) ip[y]; --y)
122 #endif /* CONFIG_IA64_HP_SIM */
125 * Very ugly, but we need this in the simulator only. Once we run on
126 * real hw, this can all go away.
128 extern void pal_emulator_static (void);
131 " .proc pal_emulator_static\n"
132 "pal_emulator_static:"
136 " cmp.gtu p6,p7=r9,r28 /* r28 <= 255? */\n"
137 "(p6) br.cond.sptk.few static\n"
141 " cmp.gtu p6,p7=r9,r28\n"
142 "(p6) br.cond.sptk.few stacked\n"
144 "static: cmp.eq p6,p7=6,r28 /* PAL_PTCE_INFO */\n"
145 "(p7) br.cond.sptk.few 1f\n"
147 " mov r8=0 /* status = 0 */\n"
148 " movl r9=0x100000000 /* tc.base */\n"
149 " movl r10=0x0000000200000003 /* count[0], count[1] */\n"
150 " movl r11=0x1000000000002000 /* stride[0], stride[1] */\n"
151 " br.cond.sptk.few rp\n"
152 "1: cmp.eq p6,p7=14,r28 /* PAL_FREQ_RATIOS */\n"
153 "(p7) br.cond.sptk.few 1f\n"
154 " mov r8=0 /* status = 0 */\n"
155 " movl r9 =0x100000064 /* proc_ratio (1/100) */\n"
156 " movl r10=0x100000100 /* bus_ratio<<32 (1/256) */\n"
157 " movl r11=0x100000064 /* itc_ratio<<32 (1/100) */\n"
159 "1: cmp.eq p6,p7=19,r28 /* PAL_RSE_INFO */\n"
160 "(p7) br.cond.sptk.few 1f\n"
161 " mov r8=0 /* status = 0 */\n"
162 " mov r9=96 /* num phys stacked */\n"
163 " mov r10=0 /* hints */\n"
165 " br.cond.sptk.few rp\n"
166 "1: cmp.eq p6,p7=1,r28 /* PAL_CACHE_FLUSH */\n"
167 "(p7) br.cond.sptk.few 1f\n"
169 " movl r8=524288 /* flush 512k million cache lines (16MB) */\n"
172 " movl r8=0xe000000000000000\n"
176 " br.cloop.sptk.few .loop\n"
184 "1: cmp.eq p6,p7=15,r28 /* PAL_PERF_MON_INFO */\n"
185 "(p7) br.cond.sptk.few 1f\n"
186 " mov r8=0 /* status = 0 */\n"
187 " movl r9 =0x12082004 /* generic=4 width=32 retired=8 cycles=18 */\n"
188 " mov r10=0 /* reserved */\n"
189 " mov r11=0 /* reserved */\n"
190 " mov r16=0xffff /* implemented PMC */\n"
191 " mov r17=0xffff /* implemented PMD */\n"
192 " add r18=8,r29 /* second index */\n"
194 " st8 [r29]=r16,16 /* store implemented PMC */\n"
195 " st8 [r18]=r0,16 /* clear remaining bits */\n"
197 " st8 [r29]=r0,16 /* store implemented PMC */\n"
198 " st8 [r18]=r0,16 /* clear remaining bits */\n"
200 " st8 [r29]=r17,16 /* store implemented PMD */\n"
201 " st8 [r18]=r0,16 /* clear remaining bits */\n"
202 " mov r16=0xf0 /* cycles count capable PMC */\n"
204 " st8 [r29]=r0,16 /* store implemented PMC */\n"
205 " st8 [r18]=r0,16 /* clear remaining bits */\n"
206 " mov r17=0x10 /* retired bundles capable PMC */\n"
208 " st8 [r29]=r16,16 /* store cycles capable */\n"
209 " st8 [r18]=r0,16 /* clear remaining bits */\n"
211 " st8 [r29]=r0,16 /* store implemented PMC */\n"
212 " st8 [r18]=r0,16 /* clear remaining bits */\n"
214 " st8 [r29]=r17,16 /* store retired bundle capable */\n"
215 " st8 [r18]=r0,16 /* clear remaining bits */\n"
217 " st8 [r29]=r0,16 /* store implemented PMC */\n"
218 " st8 [r18]=r0,16 /* clear remaining bits */\n"
220 "1: br.cond.sptk.few rp\n"
222 " br.ret.sptk.few rp\n"
223 " .endp pal_emulator_static\n");
225 /* Macro to emulate SAL call using legacy IN and OUT calls to CF8, CFC etc.. */
227 #define BUILD_CMD(addr) ((0x80000000 | (addr)) & ~3)
229 #define REG_OFFSET(addr) (0x00000000000000FF & (addr))
230 #define DEVICE_FUNCTION(addr) (0x000000000000FF00 & (addr))
231 #define BUS_NUMBER(addr) (0x0000000000FF0000 & (addr))
234 efi_get_time (efi_time_t *tm, efi_time_cap_t *tc)
236 #if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC)
238 int tv_sec; /* must be 32bits to work */
242 ssc((unsigned long) &tv32bits, 0, 0, 0, SSC_GET_TOD);
244 memset(tm, 0, sizeof(*tm));
245 offtime(tv32bits.tv_sec, tm);
248 memset(tc, 0, sizeof(*tc));
250 # error Not implemented yet...
256 efi_reset_system (int reset_type, efi_status_t status, unsigned long data_size, efi_char16_t *data)
258 #if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC)
259 ssc(status, 0, 0, 0, SSC_EXIT);
261 # error Not implemented yet...
266 efi_unimplemented (void)
268 return EFI_UNSUPPORTED;
272 sal_emulator (long index, unsigned long in1, unsigned long in2,
273 unsigned long in3, unsigned long in4, unsigned long in5,
274 unsigned long in6, unsigned long in7)
276 register long r9 asm ("r9") = 0;
277 register long r10 asm ("r10") = 0;
278 register long r11 asm ("r11") = 0;
282 * Don't do a "switch" here since that gives us code that
283 * isn't self-relocatable.
286 if (index == SAL_FREQ_BASE) {
288 case SAL_FREQ_BASE_PLATFORM:
292 case SAL_FREQ_BASE_INTERVAL_TIMER:
294 * Is this supposed to be the cr.itc frequency
295 * or something platform specific? The SAL
296 * doc ain't exactly clear on this...
301 case SAL_FREQ_BASE_REALTIME_CLOCK:
309 } else if (index == SAL_SET_VECTORS) {
311 } else if (index == SAL_GET_STATE_INFO) {
313 } else if (index == SAL_GET_STATE_INFO_SIZE) {
315 } else if (index == SAL_CLEAR_STATE_INFO) {
317 } else if (index == SAL_MC_RENDEZ) {
319 } else if (index == SAL_MC_SET_PARAMS) {
321 } else if (index == SAL_CACHE_FLUSH) {
323 } else if (index == SAL_CACHE_INIT) {
326 } else if (index == SAL_PCI_CONFIG_READ) {
328 * in1 contains the PCI configuration address and in2
329 * the size of the read. The value that is read is
330 * returned via the general register r9.
332 outl(BUILD_CMD(in1), 0xCF8);
333 if (in2 == 1) /* Reading byte */
334 r9 = inb(0xCFC + ((REG_OFFSET(in1) & 3)));
335 else if (in2 == 2) /* Reading word */
336 r9 = inw(0xCFC + ((REG_OFFSET(in1) & 2)));
337 else /* Reading dword */
339 status = PCIBIOS_SUCCESSFUL;
340 } else if (index == SAL_PCI_CONFIG_WRITE) {
342 * in1 contains the PCI configuration address, in2 the
343 * size of the write, and in3 the actual value to be
346 outl(BUILD_CMD(in1), 0xCF8);
347 if (in2 == 1) /* Writing byte */
348 outb(in3, 0xCFC + ((REG_OFFSET(in1) & 3)));
349 else if (in2 == 2) /* Writing word */
350 outw(in3, 0xCFC + ((REG_OFFSET(in1) & 2)));
351 else /* Writing dword */
353 status = PCIBIOS_SUCCESSFUL;
354 #endif /* CONFIG_PCI */
355 } else if (index == SAL_UPDATE_PAL) {
360 asm volatile ("" :: "r"(r9), "r"(r10), "r"(r11));
366 * This is here to work around a bug in egcs-1.1.1b that causes the
367 * compiler to crash (seems like a bug in the new alias analysis code.
372 return (void *) addr;
375 struct ia64_boot_param *
376 sys_fw_init (const char *args, int arglen)
378 efi_system_table_t *efi_systab;
379 efi_runtime_services_t *efi_runtime;
380 efi_config_table_t *efi_tables;
381 struct ia64_sal_systab *sal_systab;
382 efi_memory_desc_t *efi_memmap, *md;
383 unsigned long *pal_desc, *sal_desc;
384 struct ia64_sal_desc_entry_point *sal_ed;
385 struct ia64_boot_param *bp;
386 unsigned char checksum = 0;
389 # define MAKE_MD(typ, attr, start, end) \
391 md = efi_memmap + i++; \
394 md->phys_addr = start; \
396 md->num_pages = (end - start) >> 12; \
397 md->attribute = attr; \
400 memset(fw_mem, 0, sizeof(fw_mem));
402 pal_desc = (unsigned long *) &pal_emulator_static;
403 sal_desc = (unsigned long *) &sal_emulator;
406 efi_systab = (void *) cp; cp += sizeof(*efi_systab);
407 efi_runtime = (void *) cp; cp += sizeof(*efi_runtime);
408 efi_tables = (void *) cp; cp += sizeof(*efi_tables);
409 sal_systab = (void *) cp; cp += sizeof(*sal_systab);
410 sal_ed = (void *) cp; cp += sizeof(*sal_ed);
411 efi_memmap = (void *) cp; cp += NUM_MEM_DESCS*sizeof(*efi_memmap);
412 bp = (void *) cp; cp += sizeof(*bp);
413 cmd_line = (void *) cp;
418 memcpy(cmd_line, args, arglen);
422 cmd_line[arglen] = '\0';
424 memset(efi_systab, 0, sizeof(efi_systab));
425 efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
426 efi_systab->hdr.revision = EFI_SYSTEM_TABLE_REVISION;
427 efi_systab->hdr.headersize = sizeof(efi_systab->hdr);
428 efi_systab->fw_vendor = __pa("H\0e\0w\0l\0e\0t\0t\0-\0P\0a\0c\0k\0a\0r\0d\0\0");
429 efi_systab->fw_revision = 1;
430 efi_systab->runtime = __pa(efi_runtime);
431 efi_systab->nr_tables = 1;
432 efi_systab->tables = __pa(efi_tables);
434 efi_runtime->hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE;
435 efi_runtime->hdr.revision = EFI_RUNTIME_SERVICES_REVISION;
436 efi_runtime->hdr.headersize = sizeof(efi_runtime->hdr);
437 efi_runtime->get_time = __pa(&efi_get_time);
438 efi_runtime->set_time = __pa(&efi_unimplemented);
439 efi_runtime->get_wakeup_time = __pa(&efi_unimplemented);
440 efi_runtime->set_wakeup_time = __pa(&efi_unimplemented);
441 efi_runtime->set_virtual_address_map = __pa(&efi_unimplemented);
442 efi_runtime->get_variable = __pa(&efi_unimplemented);
443 efi_runtime->get_next_variable = __pa(&efi_unimplemented);
444 efi_runtime->set_variable = __pa(&efi_unimplemented);
445 efi_runtime->get_next_high_mono_count = __pa(&efi_unimplemented);
446 efi_runtime->reset_system = __pa(&efi_reset_system);
448 efi_tables->guid = SAL_SYSTEM_TABLE_GUID;
449 efi_tables->table = __pa(sal_systab);
451 /* fill in the SAL system table: */
452 memcpy(sal_systab->signature, "SST_", 4);
453 sal_systab->size = sizeof(*sal_systab);
454 sal_systab->sal_rev_minor = 1;
455 sal_systab->sal_rev_major = 0;
456 sal_systab->entry_count = 1;
458 #ifdef CONFIG_IA64_GENERIC
459 strcpy(sal_systab->oem_id, "Generic");
460 strcpy(sal_systab->product_id, "IA-64 system");
463 #ifdef CONFIG_IA64_HP_SIM
464 strcpy(sal_systab->oem_id, "Hewlett-Packard");
465 strcpy(sal_systab->product_id, "HP-simulator");
468 #ifdef CONFIG_IA64_SDV
469 strcpy(sal_systab->oem_id, "Intel");
470 strcpy(sal_systab->product_id, "SDV");
473 /* fill in an entry point: */
474 sal_ed->type = SAL_DESC_ENTRY_POINT;
475 sal_ed->pal_proc = __pa(pal_desc[0]);
476 sal_ed->sal_proc = __pa(sal_desc[0]);
477 sal_ed->gp = __pa(sal_desc[1]);
479 for (cp = (char *) sal_systab; cp < (char *) efi_memmap; ++cp)
482 sal_systab->checksum = -checksum;
485 /* simulate free memory at physical address zero */
486 MAKE_MD(EFI_BOOT_SERVICES_DATA, EFI_MEMORY_WB, 0*MB, 1*MB);
487 MAKE_MD(EFI_PAL_CODE, EFI_MEMORY_WB, 1*MB, 2*MB);
488 MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, 2*MB, 130*MB);
489 MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, 4096*MB, 4128*MB);
491 MAKE_MD( 4, 0x9, 0x0000000000000000, 0x0000000000001000);
492 MAKE_MD( 7, 0x9, 0x0000000000001000, 0x000000000008a000);
493 MAKE_MD( 4, 0x9, 0x000000000008a000, 0x00000000000a0000);
494 MAKE_MD( 5, 0x8000000000000009, 0x00000000000c0000, 0x0000000000100000);
495 MAKE_MD( 7, 0x9, 0x0000000000100000, 0x0000000004400000);
496 MAKE_MD( 2, 0x9, 0x0000000004400000, 0x0000000004be5000);
497 MAKE_MD( 7, 0x9, 0x0000000004be5000, 0x000000007f77e000);
498 MAKE_MD( 6, 0x8000000000000009, 0x000000007f77e000, 0x000000007fb94000);
499 MAKE_MD( 6, 0x8000000000000009, 0x000000007fb94000, 0x000000007fb95000);
500 MAKE_MD( 6, 0x8000000000000009, 0x000000007fb95000, 0x000000007fc00000);
501 MAKE_MD(13, 0x8000000000000009, 0x000000007fc00000, 0x000000007fc3a000);
502 MAKE_MD( 7, 0x9, 0x000000007fc3a000, 0x000000007fea0000);
503 MAKE_MD( 5, 0x8000000000000009, 0x000000007fea0000, 0x000000007fea8000);
504 MAKE_MD( 7, 0x9, 0x000000007fea8000, 0x000000007feab000);
505 MAKE_MD( 5, 0x8000000000000009, 0x000000007feab000, 0x000000007ffff000);
506 MAKE_MD( 7, 0x9, 0x00000000ff400000, 0x0000000104000000);
509 bp->efi_systab = __pa(&fw_mem);
510 bp->efi_memmap = __pa(efi_memmap);
511 bp->efi_memmap_size = NUM_MEM_DESCS*sizeof(efi_memory_desc_t);
512 bp->efi_memdesc_size = sizeof(efi_memory_desc_t);
513 bp->efi_memdesc_version = 1;
514 bp->command_line = __pa(cmd_line);
515 bp->console_info.num_cols = 80;
516 bp->console_info.num_rows = 25;
517 bp->console_info.orig_x = 0;
518 bp->console_info.orig_y = 24;