Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Added missing HVM reset function to Linux library...
[palacios.git] / bios / seabios / src / util.c
1 // Misc utility functions.
2 //
3 // Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6
7 #include "util.h" // call16
8 #include "bregs.h" // struct bregs
9 #include "config.h" // BUILD_STACK_ADDR
10
11
12 /****************************************************************
13  * 16bit calls
14  ****************************************************************/
15
16 // Call a function with a specified register state.  Note that on
17 // return, the interrupt enable/disable flag may be altered.
18 inline void
19 call16(struct bregs *callregs)
20 {
21     if (!MODESEGMENT && getesp() > BUILD_STACK_ADDR)
22         panic("call16 with invalid stack\n");
23     asm volatile(
24 #if MODE16 == 1
25         "calll __call16\n"
26         "cli\n"
27         "cld"
28 #else
29         "calll __call16_from32"
30 #endif
31         : "+a" (callregs), "+m" (*callregs)
32         :
33         : "ebx", "ecx", "edx", "esi", "edi", "cc", "memory");
34 }
35
36 inline void
37 call16big(struct bregs *callregs)
38 {
39     ASSERT32FLAT();
40     if (getesp() > BUILD_STACK_ADDR)
41         panic("call16 with invalid stack\n");
42     asm volatile(
43         "calll __call16big_from32"
44         : "+a" (callregs), "+m" (*callregs)
45         :
46         : "ebx", "ecx", "edx", "esi", "edi", "cc", "memory");
47 }
48
49 inline void
50 __call16_int(struct bregs *callregs, u16 offset)
51 {
52     if (MODESEGMENT)
53         callregs->code.seg = GET_SEG(CS);
54     else
55         callregs->code.seg = SEG_BIOS;
56     callregs->code.offset = offset;
57     call16(callregs);
58 }
59
60
61 /****************************************************************
62  * String ops
63  ****************************************************************/
64
65 // Sum the bytes in the specified area.
66 u8
67 checksum_far(u16 buf_seg, void *buf_far, u32 len)
68 {
69     SET_SEG(ES, buf_seg);
70     u32 i;
71     u8 sum = 0;
72     for (i=0; i<len; i++)
73         sum += GET_VAR(ES, ((u8*)buf_far)[i]);
74     return sum;
75 }
76
77 u8
78 checksum(void *buf, u32 len)
79 {
80     return checksum_far(GET_SEG(SS), buf, len);
81 }
82
83 size_t
84 strlen(const char *s)
85 {
86     if (__builtin_constant_p(s))
87         return __builtin_strlen(s);
88     const char *p = s;
89     while (*p)
90         p++;
91     return p-s;
92 }
93
94 // Compare two areas of memory.
95 int
96 memcmp(const void *s1, const void *s2, size_t n)
97 {
98     while (n) {
99         if (*(u8*)s1 != *(u8*)s2)
100             return *(u8*)s1 < *(u8*)s2 ? -1 : 1;
101         s1++;
102         s2++;
103         n--;
104     }
105     return 0;
106 }
107
108 // Compare two strings.
109 int
110 strcmp(const char *s1, const char *s2)
111 {
112     for (;;) {
113         if (*s1 != *s2)
114             return *s1 < *s2 ? -1 : 1;
115         if (! *s1)
116             return 0;
117         s1++;
118         s2++;
119     }
120 }
121
122 inline void
123 memset_far(u16 d_seg, void *d_far, u8 c, size_t len)
124 {
125     SET_SEG(ES, d_seg);
126     asm volatile(
127         "rep stosb %%es:(%%di)"
128         : "+c"(len), "+D"(d_far)
129         : "a"(c)
130         : "cc", "memory");
131 }
132
133 inline void
134 memset16_far(u16 d_seg, void *d_far, u16 c, size_t len)
135 {
136     len /= 2;
137     SET_SEG(ES, d_seg);
138     asm volatile(
139         "rep stosw %%es:(%%di)"
140         : "+c"(len), "+D"(d_far)
141         : "a"(c)
142         : "cc", "memory");
143 }
144
145 void *
146 memset(void *s, int c, size_t n)
147 {
148     while (n)
149         ((char *)s)[--n] = c;
150     return s;
151 }
152
153 void memset_fl(void *ptr, u8 val, size_t size)
154 {
155     if (MODESEGMENT)
156         memset_far(FLATPTR_TO_SEG(ptr), (void*)(FLATPTR_TO_OFFSET(ptr)),
157                    val, size);
158     else
159         memset(ptr, val, size);
160 }
161
162 inline void
163 memcpy_far(u16 d_seg, void *d_far, u16 s_seg, const void *s_far, size_t len)
164 {
165     SET_SEG(ES, d_seg);
166     u16 bkup_ds;
167     asm volatile(
168         "movw %%ds, %w0\n"
169         "movw %w4, %%ds\n"
170         "rep movsb (%%si),%%es:(%%di)\n"
171         "movw %w0, %%ds"
172         : "=&r"(bkup_ds), "+c"(len), "+S"(s_far), "+D"(d_far)
173         : "r"(s_seg)
174         : "cc", "memory");
175 }
176
177 inline void
178 memcpy_fl(void *d_fl, const void *s_fl, size_t len)
179 {
180     if (MODESEGMENT)
181         memcpy_far(FLATPTR_TO_SEG(d_fl), (void*)FLATPTR_TO_OFFSET(d_fl)
182                    , FLATPTR_TO_SEG(s_fl), (void*)FLATPTR_TO_OFFSET(s_fl)
183                    , len);
184     else
185         memcpy(d_fl, s_fl, len);
186 }
187
188 void *
189 #undef memcpy
190 memcpy(void *d1, const void *s1, size_t len)
191 #if MODESEGMENT == 0
192 #define memcpy __builtin_memcpy
193 #endif
194 {
195     SET_SEG(ES, GET_SEG(SS));
196     void *d = d1;
197     if (((u32)d1 | (u32)s1 | len) & 3) {
198         // non-aligned memcpy
199         asm volatile(
200             "rep movsb (%%esi),%%es:(%%edi)"
201             : "+c"(len), "+S"(s1), "+D"(d)
202             : : "cc", "memory");
203         return d1;
204     }
205     // Common case - use 4-byte copy
206     len /= 4;
207     asm volatile(
208         "rep movsl (%%esi),%%es:(%%edi)"
209         : "+c"(len), "+S"(s1), "+D"(d)
210         : : "cc", "memory");
211     return d1;
212 }
213
214 // Copy to/from memory mapped IO.  IO mem is very slow, so yield
215 // periodically.
216 void
217 iomemcpy(void *d, const void *s, u32 len)
218 {
219     yield();
220     while (len > 3) {
221         u32 copylen = len;
222         if (copylen > 2048)
223             copylen = 2048;
224         copylen /= 4;
225         len -= copylen * 4;
226         asm volatile(
227             "rep movsl (%%esi),%%es:(%%edi)"
228             : "+c"(copylen), "+S"(s), "+D"(d)
229             : : "cc", "memory");
230         yield();
231     }
232     if (len)
233         // Copy any remaining bytes.
234         memcpy(d, s, len);
235 }
236
237 void *
238 memmove(void *d, const void *s, size_t len)
239 {
240     if (s >= d)
241         return memcpy(d, s, len);
242
243     d += len-1;
244     s += len-1;
245     while (len--) {
246         *(char*)d = *(char*)s;
247         d--;
248         s--;
249     }
250
251     return d;
252 }
253
254 // Copy a string - truncating it if necessary.
255 char *
256 strtcpy(char *dest, const char *src, size_t len)
257 {
258     char *d = dest;
259     while (--len && *src != '\0')
260         *d++ = *src++;
261     *d = '\0';
262     return dest;
263 }
264
265 // locate first occurance of character c in the string s
266 char *
267 strchr(const char *s, int c)
268 {
269     for (; *s; s++)
270         if (*s == c)
271             return (char*)s;
272     return NULL;
273 }
274
275 // Remove any trailing blank characters (spaces, new lines, carriage returns)
276 void
277 nullTrailingSpace(char *buf)
278 {
279     int len = strlen(buf);
280     char *end = &buf[len-1];
281     while (end >= buf && *end <= ' ')
282         *(end--) = '\0';
283 }
284
285 /****************************************************************
286  * Keyboard calls
287  ****************************************************************/
288
289 // See if a keystroke is pending in the keyboard buffer.
290 static int
291 check_for_keystroke(void)
292 {
293     struct bregs br;
294     memset(&br, 0, sizeof(br));
295     br.flags = F_IF;
296     br.ah = 1;
297     call16_int(0x16, &br);
298     return !(br.flags & F_ZF);
299 }
300
301 // Return a keystroke - waiting forever if necessary.
302 static int
303 get_raw_keystroke(void)
304 {
305     struct bregs br;
306     memset(&br, 0, sizeof(br));
307     br.flags = F_IF;
308     call16_int(0x16, &br);
309     return br.ah;
310 }
311
312 // Read a keystroke - waiting up to 'msec' milliseconds.
313 int
314 get_keystroke(int msec)
315 {
316     u32 end = calc_future_timer(msec);
317     for (;;) {
318         if (check_for_keystroke())
319             return get_raw_keystroke();
320         if (check_timer(end))
321             return -1;
322         wait_irq();
323     }
324 }