ia64/xen-unstable

view tools/firmware/hvmloader/util.c @ 12651:9164f836943d

[HVMLOADER] Fix CFLAGS.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Nov 29 11:38:17 2006 +0000 (2006-11-29)
parents 9d6bc06919e0
children 480436ef6255
line source
1 /*
2 * util.c: Helper library functions for HVMLoader.
3 *
4 * Leendert van Doorn, leendert@watson.ibm.com
5 * Copyright (c) 2005, International Business Machines Corporation.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18 * Place - Suite 330, Boston, MA 02111-1307 USA.
19 */
21 #include "acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */
22 #include "util.h"
23 #include "config.h"
24 #include <stdint.h>
25 #include <xenctrl.h>
26 #include <xen/hvm/hvm_info_table.h>
28 void outb(uint16_t addr, uint8_t val)
29 {
30 __asm__ __volatile__ ( "outb %%al, %%dx" :: "d"(addr), "a"(val) );
31 }
33 void outw(uint16_t addr, uint16_t val)
34 {
35 __asm__ __volatile__ ( "outw %%ax, %%dx" :: "d"(addr), "a"(val) );
36 }
38 void outl(uint16_t addr, uint32_t val)
39 {
40 __asm__ __volatile__ ( "outl %%eax, %%dx" :: "d"(addr), "a"(val) );
41 }
43 uint8_t inb(uint16_t addr)
44 {
45 uint8_t val;
46 __asm__ __volatile__ ( "inb %%dx,%%al" : "=a" (val) : "d" (addr) );
47 return val;
48 }
50 uint16_t inw(uint16_t addr)
51 {
52 uint16_t val;
53 __asm__ __volatile__ ( "inw %%dx,%%ax" : "=a" (val) : "d" (addr) );
54 return val;
55 }
57 uint32_t inl(uint16_t addr)
58 {
59 uint32_t val;
60 __asm__ __volatile__ ( "inl %%dx,%%eax" : "=a" (val) : "d" (addr) );
61 return val;
62 }
64 char *itoa(char *a, unsigned int i)
65 {
66 unsigned int _i = i, x = 0;
68 do {
69 x++;
70 _i /= 10;
71 } while ( _i != 0 );
73 a += x;
74 *a-- = '\0';
76 do {
77 *a-- = (i % 10) + '0';
78 i /= 10;
79 } while ( i != 0 );
81 return a + 1;
82 }
84 int strcmp(const char *cs, const char *ct)
85 {
86 signed char res;
88 while ( ((res = *cs - *ct++) == 0) && (*cs++ != '\0') )
89 continue;
91 return res;
92 }
94 void *memcpy(void *dest, const void *src, unsigned n)
95 {
96 int t0, t1, t2;
98 __asm__ __volatile__ (
99 "cld\n"
100 "rep; movsl\n"
101 "testb $2,%b4\n"
102 "je 1f\n"
103 "movsw\n"
104 "1: testb $1,%b4\n"
105 "je 2f\n"
106 "movsb\n"
107 "2:"
108 : "=&c" (t0), "=&D" (t1), "=&S" (t2)
109 : "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
110 : "memory" );
111 return dest;
112 }
114 void *memmove(void *dest, const void *src, unsigned n)
115 {
116 if ( (long)dest > (long)src )
117 {
118 n--;
119 while ( n > 0 )
120 {
121 ((char *)dest)[n] = ((char *)src)[n];
122 n--;
123 }
124 }
125 else
126 {
127 memcpy(dest, src, n);
128 }
129 return dest;
130 }
132 char *
133 strcpy(char *dest, const char *src)
134 {
135 char *p = dest;
136 while ( *src )
137 *p++ = *src++;
138 *p = 0;
139 return dest;
140 }
142 char *
143 strncpy(char *dest, const char *src, unsigned n)
144 {
145 int i = 0;
146 char *p = dest;
148 /* write non-NUL characters from src into dest until we run
149 out of room in dest or encounter a NUL in src */
150 while ( (i < n) && *src )
151 {
152 *p++ = *src++;
153 i++;
154 }
156 /* pad remaining bytes of dest with NUL bytes */
157 while ( i < n )
158 {
159 *p++ = 0;
160 i++;
161 }
163 return dest;
164 }
166 unsigned
167 strlen(const char *s)
168 {
169 int i = 0;
170 while ( *s++ )
171 i++;
172 return i;
173 }
175 void *
176 memset(void *s, int c, unsigned n)
177 {
178 uint8_t b = (uint8_t) c;
179 uint8_t *p = (uint8_t *)s;
180 int i;
181 for ( i = 0; i < n; i++ )
182 *p++ = b;
183 return s;
184 }
186 int
187 memcmp(const void *s1, const void *s2, unsigned n)
188 {
189 unsigned i;
190 uint8_t *p1 = (uint8_t *) s1;
191 uint8_t *p2 = (uint8_t *) s2;
193 for ( i = 0; i < n; i++ )
194 {
195 if ( p1[i] < p2[i] )
196 return -1;
197 else if ( p1[i] > p2[i] )
198 return 1;
199 }
201 return 0;
202 }
204 void
205 cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
206 {
207 __asm__ __volatile__ (
208 "cpuid"
209 : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
210 : "0" (idx) );
211 }
213 /* Write a two-character hex representation of 'byte' to digits[].
214 Pre-condition: sizeof(digits) >= 2 */
215 void
216 byte_to_hex(char *digits, uint8_t byte)
217 {
218 uint8_t nybbel = byte >> 4;
220 if ( nybbel > 9 )
221 digits[0] = 'a' + nybbel-10;
222 else
223 digits[0] = '0' + nybbel;
225 nybbel = byte & 0x0f;
226 if ( nybbel > 9 )
227 digits[1] = 'a' + nybbel-10;
228 else
229 digits[1] = '0' + nybbel;
230 }
232 /* Convert an array of 16 unsigned bytes to a DCE/OSF formatted UUID
233 string.
235 Pre-condition: sizeof(dest) >= 37 */
236 void
237 uuid_to_string(char *dest, uint8_t *uuid)
238 {
239 int i = 0;
240 char *p = dest;
242 for ( i = 0; i < 4; i++ )
243 {
244 byte_to_hex(p, uuid[i]);
245 p += 2;
246 }
247 *p++ = '-';
248 for ( i = 4; i < 6; i++ )
249 {
250 byte_to_hex(p, uuid[i]);
251 p += 2;
252 }
253 *p++ = '-';
254 for ( i = 6; i < 8; i++ )
255 {
256 byte_to_hex(p, uuid[i]);
257 p += 2;
258 }
259 *p++ = '-';
260 for ( i = 8; i < 10; i++ )
261 {
262 byte_to_hex(p, uuid[i]);
263 p += 2;
264 }
265 *p++ = '-';
266 for ( i = 10; i < 16; i++ )
267 {
268 byte_to_hex(p, uuid[i]);
269 p += 2;
270 }
271 *p = '\0';
272 }
274 #include <xen/hvm/e820.h>
275 #define E820_MAP_NR ((unsigned char *)E820_MAP_PAGE + E820_MAP_NR_OFFSET)
276 #define E820_MAP ((struct e820entry *)(E820_MAP_PAGE + E820_MAP_OFFSET))
277 uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask)
278 {
279 uint64_t addr = 0;
280 int c = *E820_MAP_NR - 1;
281 struct e820entry *e820entry = (struct e820entry *)E820_MAP;
283 while ( c >= 0 )
284 {
285 if ( (e820entry[c].type == E820_RAM) &&
286 ((e820entry[c].addr & (~mask)) == 0) &&
287 (e820entry[c].size >= size) )
288 {
289 addr = e820entry[c].addr;
290 if ( e820entry[c].size != size )
291 {
292 (*E820_MAP_NR)++;
293 memmove(&e820entry[c+1],
294 &e820entry[c],
295 (*E820_MAP_NR - c) *
296 sizeof(struct e820entry));
297 e820entry[c].size -= size;
298 addr += e820entry[c].size;
299 c++;
300 }
301 e820entry[c].addr = addr;
302 e820entry[c].size = size;
303 e820entry[c].type = type;
304 break;
305 }
306 c--;
307 }
308 return addr;
309 }
311 uint32_t ioapic_read(uint32_t reg)
312 {
313 *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00) = reg;
314 return *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10);
315 }
317 void ioapic_write(uint32_t reg, uint32_t val)
318 {
319 *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00) = reg;
320 *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10) = val;
321 }
323 uint32_t lapic_read(uint32_t reg)
324 {
325 return *(volatile uint32_t *)(LAPIC_BASE_ADDRESS + reg);
326 }
328 void lapic_write(uint32_t reg, uint32_t val)
329 {
330 *(volatile uint32_t *)(LAPIC_BASE_ADDRESS + reg) = val;
331 }
333 #define PCI_CONF1_ADDRESS(bus, devfn, reg) \
334 (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
336 uint32_t pci_read(uint32_t devfn, uint32_t reg, uint32_t len)
337 {
338 outl(0xcf8, PCI_CONF1_ADDRESS(0, devfn, reg));
340 switch ( len )
341 {
342 case 1: return inb(0xcfc + (reg & 3));
343 case 2: return inw(0xcfc + (reg & 2));
344 }
346 return inl(0xcfc);
347 }
349 void pci_write(uint32_t devfn, uint32_t reg, uint32_t len, uint32_t val)
350 {
351 outl(0xcf8, PCI_CONF1_ADDRESS(0, devfn, reg));
353 switch ( len )
354 {
355 case 1: outb(0xcfc + (reg & 3), val); break;
356 case 2: outw(0xcfc + (reg & 2), val); break;
357 case 4: outl(0xcfc, val); break;
358 }
359 }
361 static char *printnum(char *p, unsigned long num, int base)
362 {
363 unsigned long n;
365 if ( (n = num/base) > 0 )
366 p = printnum(p, n, base);
367 *p++ = "0123456789abcdef"[(int)(num % base)];
368 *p = '\0';
369 return p;
370 }
372 static void _doprint(void (*put)(char), char const *fmt, va_list ap)
373 {
374 register char *str, c;
375 int lflag, zflag, nflag;
376 char buffer[17];
377 unsigned value;
378 int i, slen, pad;
380 for ( ; *fmt != '\0'; fmt++ )
381 {
382 if ( *fmt != '%' )
383 {
384 put(*fmt);
385 continue;
386 }
388 pad = zflag = nflag = lflag = 0;
389 c = *++fmt;
390 if ( (c == '-') || isdigit(c) )
391 {
392 if ( c == '-' )
393 {
394 nflag = 1;
395 c = *++fmt;
396 }
397 zflag = c == '0';
398 for ( pad = 0; isdigit(c); c = *++fmt )
399 pad = (pad * 10) + c - '0';
400 }
401 if ( c == 'l' ) /* long extension */
402 {
403 lflag = 1;
404 c = *++fmt;
405 }
406 if ( (c == 'd') || (c == 'u') || (c == 'o') || (c == 'x') )
407 {
408 if ( lflag )
409 value = va_arg(ap, unsigned);
410 else
411 value = (unsigned) va_arg(ap, unsigned int);
412 str = buffer;
413 printnum(str, value,
414 c == 'o' ? 8 : (c == 'x' ? 16 : 10));
415 goto printn;
416 }
417 else if ( (c == 'O') || (c == 'D') || (c == 'X') )
418 {
419 value = va_arg(ap, unsigned);
420 str = buffer;
421 printnum(str, value,
422 c == 'O' ? 8 : (c == 'X' ? 16 : 10));
423 printn:
424 slen = strlen(str);
425 for ( i = pad - slen; i > 0; i-- )
426 put(zflag ? '0' : ' ');
427 while ( *str )
428 put(*str++);
429 }
430 else if ( c == 's' )
431 {
432 str = va_arg(ap, char *);
433 slen = strlen(str);
434 if ( nflag == 0 )
435 for ( i = pad - slen; i > 0; i-- )
436 put(' ');
437 while ( *str )
438 put(*str++);
439 if ( nflag )
440 for ( i = pad - slen; i > 0; i-- )
441 put(' ');
442 }
443 else if ( c == 'c' )
444 {
445 put(va_arg(ap, int));
446 }
447 else
448 {
449 put(*fmt);
450 }
451 }
452 }
454 static void putchar(char c)
455 {
456 outb(0xe9, c);
457 }
459 int printf(const char *fmt, ...)
460 {
461 va_list ap;
463 va_start(ap, fmt);
464 _doprint(putchar, fmt, ap);
465 va_end(ap);
467 return 0;
468 }
470 int vprintf(const char *fmt, va_list ap)
471 {
472 _doprint(putchar, fmt, ap);
473 return 0;
474 }
476 void __assert_failed(char *assertion, char *file, int line)
477 {
478 printf("HVMLoader assertion '%s' failed at %s:%d\n",
479 assertion, file, line);
480 for ( ; ; )
481 __asm__ __volatile__ ( "ud2" );
482 }
484 void __bug(char *file, int line)
485 {
486 printf("HVMLoader bug at %s:%d\n", file, line);
487 for ( ; ; )
488 __asm__ __volatile__ ( "ud2" );
489 }
491 static int validate_hvm_info(struct hvm_info_table *t)
492 {
493 char signature[] = "HVM INFO";
494 uint8_t *ptr = (uint8_t *)t;
495 uint8_t sum = 0;
496 int i;
498 /* strncmp(t->signature, "HVM INFO", 8) */
499 for ( i = 0; i < 8; i++ )
500 {
501 if ( signature[i] != t->signature[i] )
502 {
503 printf("Bad hvm info signature\n");
504 return 0;
505 }
506 }
508 for ( i = 0; i < t->length; i++ )
509 sum += ptr[i];
511 return (sum == 0);
512 }
514 static struct hvm_info_table *get_hvm_info_table(void)
515 {
516 static struct hvm_info_table *table;
517 struct hvm_info_table *t;
519 if ( table != NULL )
520 return table;
522 t = (struct hvm_info_table *)HVM_INFO_PADDR;
524 if ( !validate_hvm_info(t) )
525 {
526 printf("Bad hvm info table\n");
527 return NULL;
528 }
530 table = t;
532 return table;
533 }
535 int get_vcpu_nr(void)
536 {
537 struct hvm_info_table *t = get_hvm_info_table();
538 return (t ? t->nr_vcpus : 1);
539 }
541 int get_acpi_enabled(void)
542 {
543 struct hvm_info_table *t = get_hvm_info_table();
544 return (t ? t->acpi_enabled : 1);
545 }
547 int get_apic_mode(void)
548 {
549 struct hvm_info_table *t = get_hvm_info_table();
550 return (t ? t->apic_mode : 1);
551 }
553 /*
554 * Local variables:
555 * mode: C
556 * c-set-style: "BSD"
557 * c-basic-offset: 4
558 * tab-width: 4
559 * indent-tabs-mode: nil
560 * End:
561 */