Kernel/x86 - Removed PAE support
[tpg/acess2.git] / Kernel / lib.c
1 /*
2  * Acess2
3  * Common Library Functions
4  */
5 #include <acess.h>
6
7 // === CONSTANTS ===
8 #define RANDOM_SEED     0xACE55052
9 #define RANDOM_A        0x00731ADE
10 #define RANDOM_C        12345
11 #define RANDOM_SPRUCE   0xf12b039
12 //                          Jan Feb Mar Apr May  Jun  Jul  Aug  Sept Oct  Nov  Dec
13 const short DAYS_BEFORE[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
14 #define UNIX_TO_2K      ((30*365*3600*24) + (7*3600*24))        //Normal years + leap years
15
16 // === PROTOTYPES ===
17 #if 0
18  int    atoi(const char *string);
19 void    itoa(char *buf, Uint64 num, int base, int minLength, char pad);
20  int    vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args);
21  int    sprintf(char *__s, const char *__format, ...);
22 #endif
23  int    tolower(int c);
24 #if 0
25  int    strucmp(const char *Str1, const char *Str2);
26 char    *strchr(const char *__s, int __c);
27  int    strpos(const char *Str, char Ch);
28  Uint8  ByteSum(void *Ptr, int Size);
29 size_t  strlen(const char *__s);
30 char    *strcpy(char *__str1, const char *__str2);
31 char    *strncpy(char *__str1, const char *__str2, size_t max);
32  int    strcmp(const char *str1, const char *str2);
33  int    strncmp(const char *str1, const char *str2, size_t num);
34 char    *_strdup(const char *File, int Line, const char *Str);
35 char    **str_split(const char *__str, char __ch);
36  int    strpos8(const char *str, Uint32 Search);
37  int    ReadUTF8(Uint8 *str, Uint32 *Val);
38  int    WriteUTF8(Uint8 *str, Uint32 Val);
39  int    DivUp(int num, int dem);
40 Sint64  timestamp(int sec, int mins, int hrs, int day, int month, int year);
41  int    rand(void);
42  
43  int    CheckString(char *String);
44  int    CheckMem(void *Mem, int NumBytes);
45  
46  int    ModUtil_LookupString(char **Array, char *Needle);
47  int    ModUtil_SetIdent(char *Dest, char *Value);
48  
49  int    UnHex(Uint8 *Dest, size_t DestSize, const char *SourceString);
50 #endif
51
52 // === EXPORTS ===
53 EXPORT(atoi);
54 EXPORT(itoa);
55 EXPORT(vsnprintf);
56 EXPORT(sprintf);
57 EXPORT(tolower);
58 EXPORT(strucmp);
59 EXPORT(strchr);
60 EXPORT(strpos);
61 EXPORT(ByteSum);
62 EXPORT(strlen);
63 EXPORT(strcpy);
64 EXPORT(strncpy);
65 EXPORT(strcat);
66 EXPORT(strncat);
67 EXPORT(strcmp);
68 EXPORT(strncmp);
69 //EXPORT(strdup);
70 EXPORT(_strdup);        // Takes File/Line too
71 EXPORT(str_split);
72 EXPORT(strpos8);
73 EXPORT(DivUp);
74 EXPORT(ReadUTF8);
75 EXPORT(WriteUTF8);
76 EXPORT(timestamp);
77 EXPORT(CheckString);
78 EXPORT(CheckMem);
79 EXPORT(ModUtil_LookupString);
80 EXPORT(ModUtil_SetIdent);
81 EXPORT(UnHex);
82 EXPORT(SwapEndian16);
83 EXPORT(SwapEndian32);
84
85 // === CODE ===
86 /**
87  * \brief Convert a string into an integer
88  */
89 int atoi(const char *string)
90 {
91          int    ret = 0;
92          int    bNeg = 0;
93         
94         //Log("atoi: (string='%s')", string);
95         
96         // Clear non-numeric characters
97         while( !('0' <= *string && *string <= '9') && *string != '-' )  string++;
98         if( *string == '-' ) {
99                 bNeg = 1;
100                 while( !('0' <= *string && *string <= '9') )    string++;
101         }
102         
103         if(*string == '0')
104         {
105                 string ++;
106                 if(*string == 'x')
107                 {
108                         // Hex
109                         string ++;
110                         for( ;; string ++ )
111                         {
112                                 if('0' <= *string && *string <= '9') {
113                                         ret *= 16;
114                                         ret += *string - '0';
115                                 }
116                                 else if('A' <= *string && *string <= 'F') {
117                                         ret *= 16;
118                                         ret += *string - 'A' + 10;
119                                 }
120                                 else if('a' <= *string && *string <= 'f') {
121                                         ret *= 16;
122                                         ret += *string - 'a' + 10;
123                                 }
124                                 else
125                                         break;
126                         }
127                 }
128                 else    // Octal
129                 {
130                         for( ; '0' <= *string && *string <= '7'; string ++ )
131                         {
132                                 ret *= 8;
133                                 ret += *string - '0';
134                         }
135                 }
136         }
137         else    // Decimal
138         {
139                 for( ; '0' <= *string && *string <= '9'; string++)
140                 {
141                         ret *= 10;
142                         ret += *string - '0';
143                 }
144         }
145         
146         if(bNeg)        ret = -ret;
147         
148         //Log("atoi: RETURN %i", ret);
149         
150         return ret;
151 }
152
153 static const char cUCDIGITS[] = "0123456789ABCDEF";
154 /**
155  * \fn void itoa(char *buf, Uint64 num, int base, int minLength, char pad)
156  * \brief Convert an integer into a character string
157  */
158 void itoa(char *buf, Uint64 num, int base, int minLength, char pad)
159 {
160         char    tmpBuf[64+1];
161          int    pos=0, i;
162
163         // Sanity check
164         if(!buf)        return;
165         
166         // Sanity Check
167         if(base > 16 || base < 2) {
168                 buf[0] = 0;
169                 return;
170         }
171         
172         // Convert 
173         while(num > base-1) {
174                 tmpBuf[pos] = cUCDIGITS[ num % base ];
175                 num /= (Uint)base;              // Shift `num` right 1 digit
176                 pos++;
177         }
178         tmpBuf[pos++] = cUCDIGITS[ num % base ];                // Last digit of `num`
179         
180         // Put in reverse
181         i = 0;
182         minLength -= pos;
183         while(minLength-- > 0)  buf[i++] = pad;
184         while(pos-- > 0)                buf[i++] = tmpBuf[pos]; // Reverse the order of characters
185         buf[i] = 0;
186 }
187
188 /**
189  * \brief Append a character the the vsnprintf output
190  */
191 #define PUTCH(c)        do{\
192         char ch=(c);\
193         if(pos==__maxlen){return pos;}\
194         if(__s){__s[pos++]=ch;}else{pos++;}\
195         }while(0)
196 #define GETVAL()        do {\
197         if(isLongLong)  val = va_arg(args, Uint64);\
198         else    val = va_arg(args, unsigned int);\
199         }while(0)
200 /**
201  * \brief VArg String Number Print Formatted
202  */
203 int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
204 {
205         char    c, pad = ' ';
206          int    minSize = 0, precision = -1, len;
207         char    tmpBuf[34];     // For Integers
208         const char      *p = NULL;
209          int    isLongLong = 0;
210         Uint64  val;
211         size_t  pos = 0;
212         // Flags
213          int    bPadLeft = 0;
214         
215         //Log("vsnprintf: (__s=%p, __maxlen=%i, __format='%s', ...)", __s, __maxlen, __format);
216         
217         while((c = *__format++) != 0)
218         {
219                 // Non control character
220                 if(c != '%') { PUTCH(c); continue; }
221                 
222                 c = *__format++;
223                 //Log("pos = %i", pos);
224                 
225                 // Literal %
226                 if(c == '%') { PUTCH('%'); continue; }
227                 
228                 // Pointer - Done first for debugging
229                 if(c == 'p') {
230                         Uint    ptr = va_arg(args, Uint);
231                         PUTCH('*');     PUTCH('0');     PUTCH('x');
232                         itoa(tmpBuf, ptr, 16, BITS/4, '0');
233                         p = tmpBuf;
234                         goto printString;
235                 }
236                 
237                 // - Padding Side Flag
238                 if(c == '-') {
239                         bPadLeft = 1;
240                         c = *__format++;
241                 }
242                 
243                 // - Padding
244                 if(c == '0') {
245                         pad = '0';
246                         c = *__format++;
247                 }
248                 else
249                         pad = ' ';
250                 
251                 // - Minimum length
252                 if(c == '*') {  // Dynamic length
253                         minSize = va_arg(args, unsigned int);
254                         c = *__format++;
255                 }
256                 else if('1' <= c && c <= '9')
257                 {
258                         minSize = 0;
259                         while('0' <= c && c <= '9')
260                         {
261                                 minSize *= 10;
262                                 minSize += c - '0';
263                                 c = *__format++;
264                         }
265                 }
266                 else
267                         minSize = 0;
268                 
269                 // - Precision
270                 precision = -1;
271                 if( c == '.' ) {
272                         c = *__format++;
273                         
274                         if(c == '*') {  // Dynamic length
275                                 precision = va_arg(args, unsigned int);
276                                 c = *__format++;
277                         }
278                         else if('1' <= c && c <= '9')
279                         {
280                                 precision = 0;
281                                 while('0' <= c && c <= '9')
282                                 {
283                                         precision *= 10;
284                                         precision += c - '0';
285                                         c = *__format++;
286                                 }
287                         }
288                 }
289                 
290                 // - Default, Long or LongLong?
291                 isLongLong = 0;
292                 if(c == 'l')    // Long is actually the default on x86
293                 {
294                         c = *__format++;
295                         if(c == 'l') {
296                                 c = *__format++;
297                                 isLongLong = 1;
298                         }
299                 }
300                 
301                 // - Now get the format code
302                 p = tmpBuf;
303                 switch(c)
304                 {
305                 case 'd':
306                 case 'i':
307                         GETVAL();
308                         if( isLongLong && val >> 63 ) {
309                                 PUTCH('-');
310                                 val = -val;
311                         }
312                         else if( !isLongLong && val >> 31 ) {
313                                 PUTCH('-');
314                                 val = -(Sint32)val;
315                         }
316                         itoa(tmpBuf, val, 10, minSize, pad);
317                         goto printString;
318                 case 'u':       // Unsigned
319                         GETVAL();
320                         itoa(tmpBuf, val, 10, minSize, pad);
321                         goto printString;
322                 case 'P':       // Physical Address
323                         PUTCH('0');
324                         PUTCH('x');
325                         if(sizeof(tPAddr) > 4)  isLongLong = 1;
326                         GETVAL();
327                         itoa(tmpBuf, val, 16, minSize, pad);
328                         goto printString;
329                 case 'X':       // Hex
330                         if(BITS == 64)
331                                 isLongLong = 1; // TODO: Handle non-x86 64-bit archs
332                         GETVAL();
333                         itoa(tmpBuf, val, 16, minSize, pad);
334                         goto printString;
335                         
336                 case 'x':       // Lower case hex
337                         GETVAL();
338                         itoa(tmpBuf, val, 16, minSize, pad);
339                         goto printString;
340                 case 'o':       // Octal
341                         GETVAL();
342                         itoa(tmpBuf, val, 8, minSize, pad);
343                         goto printString;
344                 case 'b':
345                         GETVAL();
346                         itoa(tmpBuf, val, 2, minSize, pad);
347                         goto printString;
348
349                 case 'B':       //Boolean
350                         val = va_arg(args, unsigned int);
351                         if(val) p = "True";
352                         else    p = "False";
353                         goto printString;
354                 
355                 // String - Null Terminated Array
356                 case 's':
357                         p = va_arg(args, char*);        // Get Argument
358                         if( !CheckString(p) )   p = "(inval)";  // Avoid #PFs  
359                 printString:
360                         if(!p)          p = "(null)";
361                         len = strlen(p);
362                         if( !bPadLeft ) while(len++ < minSize)  PUTCH(pad);
363                         while(*p && precision--)        PUTCH(*p++);
364                         if( bPadLeft )  while(len++ < minSize)  PUTCH(pad);
365                         break;
366                 
367                 case 'C':       // Non-Null Terminated Character Array
368                         p = va_arg(args, char*);
369                         if( !CheckMem(p, minSize) )     continue;       // No #PFs please
370                         if(!p)  goto printString;
371                         while(minSize--)        PUTCH(*p++);
372                         break;
373                 
374                 // Single Character
375                 case 'c':
376                 default:
377                         GETVAL();
378                         PUTCH( (Uint8)val );
379                         break;
380                 }
381         }
382         
383         if(__s && pos != __maxlen)
384                 __s[pos] = '\0';
385         
386         return pos;
387 }
388 #undef PUTCH
389
390 /**
391  */
392 int sprintf(char *__s, const char *__format, ...)
393 {
394         va_list args;
395          int    ret;
396         
397         va_start(args, __format);
398         ret = vsnprintf(__s, -1, __format, args);
399         va_end(args);
400         
401         return ret;
402 }
403
404 /**
405  * \fn int tolower(int c)
406  * \brief Converts a character to lower case
407  */
408 int tolower(int c)
409 {
410         if('A' <= c && c <= 'Z')
411                 return c - 'A' + 'a';
412         return c;
413 }
414
415 /**
416  * \fn int strucmp(const char *Str1, const char *Str2)
417  * \brief Compare \a Str1 and \a Str2 case-insensitively
418  */
419 int strucmp(const char *Str1, const char *Str2)
420 {
421         while(*Str1 && tolower(*Str1) == tolower(*Str2))
422                 Str1++, Str2++;
423         return tolower(*Str1) - tolower(*Str2);
424 }
425
426 /**
427  * \brief Locate a byte in a string
428  */
429 char *strchr(const char *__s, int __c)
430 {
431         for( ; *__s; __s ++ )
432         {
433                 if( *__s == __c )       return (char*)__s;
434         }
435         return NULL;
436 }
437
438 /**
439  * \fn int strpos(const char *Str, char Ch)
440  * \brief Search a string for an ascii character
441  */
442 int strpos(const char *Str, char Ch)
443 {
444          int    pos;
445         for(pos=0;Str[pos];pos++)
446         {
447                 if(Str[pos] == Ch)      return pos;
448         }
449         return -1;
450 }
451
452 /**
453  * \fn Uint8 ByteSum(void *Ptr, int Size)
454  * \brief Adds the bytes in a memory region and returns the sum
455  */
456 Uint8 ByteSum(const void *Ptr, int Size)
457 {
458         Uint8   sum = 0;
459         const Uint8     *data = Ptr;
460         while(Size--)   sum += *(data++);
461         return sum;
462 }
463
464 /**
465  * \fn size_t strlen(const char *__str)
466  * \brief Get the length of string
467  */
468 size_t strlen(const char *__str)
469 {
470         size_t  ret = 0;
471         while(*__str++) ret++;
472         return ret;
473 }
474
475 /**
476  * \brief Copy a string to a new location
477  */
478 char *strcpy(char *__str1, const char *__str2)
479 {
480         while(*__str2)
481                 *__str1++ = *__str2++;
482         *__str1 = '\0'; // Terminate String
483         return __str1;
484 }
485
486 /**
487  * \brief Copy a string to a new location
488  * \note Copies at most `max` chars
489  */
490 char *strncpy(char *__str1, const char *__str2, size_t max)
491 {
492         while(*__str2 && max-- >= 1)
493                 *__str1++ = *__str2++;
494         if(max)
495                 *__str1 = '\0'; // Terminate String
496         return __str1;
497 }
498
499 /**
500  * \brief Append a string to another
501  */
502 char *strcat(char *__dest, const char *__src)
503 {
504         while(*__dest++);
505         __dest--;
506         while(*__src)
507                 *__dest++ = *__src++;
508         *__dest = '\0';
509         return __dest;
510 }
511
512 /**
513  * \brief Append at most \a n chars to a string from another
514  * \note At most n+1 chars are written (the dest is always zero terminated)
515  */
516 char *strncat(char *__dest, const char *__src, size_t n)
517 {
518         while(*__dest++);
519         while(*__src && n-- >= 1)
520                 *__dest++ = *__src++;
521         *__dest = '\0';
522         return __dest;
523 }
524
525 /**
526  * \fn int strcmp(const char *str1, const char *str2)
527  * \brief Compare two strings return the difference between
528  *        the first non-matching characters.
529  */
530 int strcmp(const char *str1, const char *str2)
531 {
532         while(*str1 && *str1 == *str2)
533                 str1++, str2++;
534         return *str1 - *str2;
535 }
536
537 /**
538  * \fn int strncmp(const char *Str1, const char *Str2, size_t num)
539  * \brief Compare strings \a Str1 and \a Str2 to a maximum of \a num characters
540  */
541 int strncmp(const char *Str1, const char *Str2, size_t num)
542 {
543         if(num == 0)    return 0;       // TODO: Check what should officially happen here
544         while(--num && *Str1 && *Str1 == *Str2)
545                 Str1++, Str2++;
546         return *Str1-*Str2;
547 }
548
549 #if 0
550 /**
551  * \fn char *strdup(const char *Str)
552  * \brief Duplicates a string
553  */
554 char *strdup(const char *Str)
555 {
556         char    *ret;
557         ret = malloc(strlen(Str)+1);
558         if( !ret )      return NULL;
559         strcpy(ret, Str);
560         return ret;
561 }
562 #else
563
564 /**
565  * \fn char *_strdup(const char *File, int Line, const char *Str)
566  * \brief Duplicates a string
567  */
568 char *_strdup(const char *File, int Line, const char *Str)
569 {
570         char    *ret;
571         ret = Heap_Allocate(File, Line, strlen(Str)+1);
572         if( !ret )      return NULL;
573         strcpy(ret, Str);
574         return ret;
575 }
576 #endif
577
578 /**
579  * \brief Split a string using the passed character
580  * \return NULL terminated array of strings on the heap
581  * \param __str String to split
582  * \param __ch  Character to split by
583  */
584 char **str_split(const char *__str, char __ch)
585 {
586          int    i, j;
587          int    len = 1;
588         char    **ret;
589         char    *start;
590         
591         for( i = 0; __str[i]; i++ )
592         {
593                 if(__str[i] == __ch)
594                         len ++;
595         }
596         
597         ret = malloc( sizeof(char*)*(len+1) + (i + 1) );
598         if( !ret )      return NULL;
599         
600         j = 1;
601         start = (char *)&ret[len+1];
602         ret[0] = start;
603         for( i = 0; __str[i]; i++ )
604         {
605                 if(__str[i] == __ch) {
606                         *start++ = '\0';
607                         ret[j++] = start;
608                 }
609                 else {
610                         *start++ = __str[i]; 
611                 }
612         }
613         *start = '\0';
614         ret[j] = NULL;
615         
616         return ret;
617 }
618
619 /**
620  * \fn int DivUp(int num, int dem)
621  * \brief Divide two numbers, rounding up
622  * \param num   Numerator
623  * \param dem   Denominator
624  */
625 int DivUp(int num, int dem)
626 {
627         return (num+dem-1)/dem;
628 }
629
630 /**
631  * \fn int strpos8(const char *str, Uint32 search)
632  * \brief Search a string for a UTF-8 character
633  */
634 int strpos8(const char *str, Uint32 Search)
635 {
636          int    pos;
637         Uint32  val = 0;
638         for(pos=0;str[pos];pos++)
639         {
640                 // ASCII Range
641                 if(Search < 128) {
642                         if(str[pos] == Search)  return pos;
643                         continue;
644                 }
645                 if(*(Uint8*)(str+pos) < 128)    continue;
646                 
647                 pos += ReadUTF8( (Uint8*)&str[pos], &val );
648                 if(val == Search)       return pos;
649         }
650         return -1;
651 }
652
653 /**
654  * \fn int ReadUTF8(Uint8 *str, Uint32 *Val)
655  * \brief Read a UTF-8 character from a string
656  */
657 int ReadUTF8(const Uint8 *str, Uint32 *Val)
658 {
659         *Val = 0xFFFD;  // Assume invalid character
660         
661         // ASCII
662         if( !(*str & 0x80) ) {
663                 *Val = *str;
664                 return 1;
665         }
666         
667         // Middle of a sequence
668         if( (*str & 0xC0) == 0x80 ) {
669                 return 1;
670         }
671         
672         // Two Byte
673         if( (*str & 0xE0) == 0xC0 ) {
674                 *Val = (*str & 0x1F) << 6;      // Upper 6 Bits
675                 str ++;
676                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
677                 *Val |= (*str & 0x3F);  // Lower 6 Bits
678                 return 2;
679         }
680         
681         // Three Byte
682         if( (*str & 0xF0) == 0xE0 ) {
683                 *Val = (*str & 0x0F) << 12;     // Upper 4 Bits
684                 str ++;
685                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
686                 *Val |= (*str & 0x3F) << 6;     // Middle 6 Bits
687                 str ++;
688                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
689                 *Val |= (*str & 0x3F);  // Lower 6 Bits
690                 return 3;
691         }
692         
693         // Four Byte
694         if( (*str & 0xF1) == 0xF0 ) {
695                 *Val = (*str & 0x07) << 18;     // Upper 3 Bits
696                 str ++;
697                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
698                 *Val |= (*str & 0x3F) << 12;    // Middle-upper 6 Bits
699                 str ++;
700                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
701                 *Val |= (*str & 0x3F) << 6;     // Middle-lower 6 Bits
702                 str ++;
703                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
704                 *Val |= (*str & 0x3F);  // Lower 6 Bits
705                 return 4;
706         }
707         
708         // UTF-8 Doesn't support more than four bytes
709         return 4;
710 }
711
712 /**
713  * \fn int WriteUTF8(Uint8 *str, Uint32 Val)
714  * \brief Write a UTF-8 character sequence to a string
715  */
716 int WriteUTF8(Uint8 *str, Uint32 Val)
717 {
718         // ASCII
719         if( Val < 128 ) {
720                 *str = Val;
721                 return 1;
722         }
723         
724         // Two Byte
725         if( Val < 0x8000 ) {
726                 *str = 0xC0 | (Val >> 6);
727                 str ++;
728                 *str = 0x80 | (Val & 0x3F);
729                 return 2;
730         }
731         
732         // Three Byte
733         if( Val < 0x10000 ) {
734                 *str = 0xE0 | (Val >> 12);
735                 str ++;
736                 *str = 0x80 | ((Val >> 6) & 0x3F);
737                 str ++;
738                 *str = 0x80 | (Val & 0x3F);
739                 return 3;
740         }
741         
742         // Four Byte
743         if( Val < 0x110000 ) {
744                 *str = 0xF0 | (Val >> 18);
745                 str ++;
746                 *str = 0x80 | ((Val >> 12) & 0x3F);
747                 str ++;
748                 *str = 0x80 | ((Val >> 6) & 0x3F);
749                 str ++;
750                 *str = 0x80 | (Val & 0x3F);
751                 return 4;
752         }
753         
754         // UTF-8 Doesn't support more than four bytes
755         return 0;
756 }
757
758 /**
759  * \fn Uint64 timestamp(int sec, int mins, int hrs, int day, int month, int year)
760  * \brief Converts a date into an Acess Timestamp
761  */
762 Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year)
763 {
764         Sint64  stamp;
765         stamp = sec;
766         stamp += mins*60;
767         stamp += hrs*3600;
768         
769         stamp += day*3600*24;
770         stamp += month*DAYS_BEFORE[month]*3600*24;
771         if(     (
772                 ((year&3) == 0 || year%100 != 0)
773                 || (year%100 == 0 && ((year/100)&3) == 0)
774                 ) && month > 1) // Leap year and after feb
775                 stamp += 3600*24;
776         
777         stamp += ((365*4+1) * ((year-2000)&~3)) * 3600*24;      // Four Year Segments
778         stamp += ((year-2000)&3) * 365*3600*24; // Inside four year segment
779         stamp += UNIX_TO_2K;
780         
781         return stamp * 1000;
782 }
783
784 /**
785  * \fn int rand()
786  * \brief Pseudo random number generator
787  */
788 int rand(void)
789 {
790         #if 0
791         static Uint     state = RANDOM_SEED;
792         Uint    old = state;
793         // Get the next state value
794         giRandomState = (RANDOM_A*state + RANDOM_C);
795         // Check if it has changed, and if it hasn't, change it
796         if(state == old)        state += RANDOM_SPRUCE;
797         return state;
798         #else
799         // http://en.wikipedia.org/wiki/Xorshift
800         // 2010-10-03
801         static Uint32   x = 123456789;
802         static Uint32   y = 362436069;
803         static Uint32   z = 521288629;
804         static Uint32   w = 88675123; 
805         Uint32  t;
806  
807         t = x ^ (x << 11);
808         x = y; y = z; z = w;
809         return w = w ^ (w >> 19) ^ t ^ (t >> 8); 
810         #endif
811 }
812
813 /* *
814  * \name Memory Validation
815  * \{
816  */
817 /**
818  * \brief Checks if a string resides fully in valid memory
819  */
820 int CheckString(const char *String)
821 {
822         if( !MM_GetPhysAddr( (tVAddr)String ) )
823                 return 0;
824         
825         // Check 1st page
826         if( MM_IsUser( (tVAddr)String ) )
827         {
828                 // Traverse String
829                 while( *String )
830                 {
831                         if( !MM_IsUser( (tVAddr)String ) )
832                                 return 0;
833                         // Increment string pointer
834                         String ++;
835                 }
836                 return 1;
837         }
838         else if( MM_GetPhysAddr( (tVAddr)String ) )
839         {
840                 // Traverse String
841                 while( *String )
842                 {
843                         if( !MM_GetPhysAddr( (tVAddr)String ) )
844                                 return 0;
845                         // Increment string pointer
846                         String ++;
847                 }
848                 return 1;
849         }
850         return 0;
851 }
852
853 /**
854  * \brief Check if a sized memory region is valid memory
855  */
856 int CheckMem(const void *Mem, int NumBytes)
857 {
858         tVAddr  addr = (tVAddr)Mem;
859         
860         if( MM_IsUser( addr ) )
861         {
862                 while( NumBytes-- )
863                 {
864                         if( !MM_IsUser( addr ) )
865                                 return 0;
866                         addr ++;
867                 }
868                 return 1;
869         }
870         else if( MM_GetPhysAddr( addr ) )
871         {
872                 while( NumBytes-- )
873                 {
874                         if( !MM_GetPhysAddr( addr ) )
875                                 return 0;
876                         addr ++;
877                 }
878                 return 1;
879         }
880         return 0;
881 }
882 /* *
883  * \}
884  */
885
886 /**
887  * \brief Search a string array for \a Needle
888  * \note Helper function for eTplDrv_IOCtl::DRV_IOCTL_LOOKUP
889  */
890 int ModUtil_LookupString(const char **Array, const char *Needle)
891 {
892          int    i;
893         if( !CheckString(Needle) )      return -1;
894         for( i = 0; Array[i]; i++ )
895         {
896                 if(strcmp(Array[i], Needle) == 0)       return i;
897         }
898         return -1;
899 }
900
901 int ModUtil_SetIdent(char *Dest, const char *Value)
902 {
903         if( !CheckMem(Dest, 32) )       return -1;
904         strncpy(Dest, Value, 32);
905         return 1;
906 }
907
908 /**
909  * \brief Convert a string of hexadecimal digits into a byte stream
910  */
911 int UnHex(Uint8 *Dest, size_t DestSize, const char *SourceString)
912 {
913          int    i;
914         
915         for( i = 0; i < DestSize*2; i += 2 )
916         {
917                 Uint8   val = 0;
918                 
919                 if(SourceString[i] == '\0')     break;
920                 
921                 if('0' <= SourceString[i] && SourceString[i] <= '9')
922                         val |= (SourceString[i]-'0') << 4;
923                 else if('A' <= SourceString[i] && SourceString[i] <= 'F')
924                         val |= (SourceString[i]-'A'+10) << 4;
925                 else if('a' <= SourceString[i] && SourceString[i] <= 'f')
926                         val |= (SourceString[i]-'a'+10) << 4;
927                         
928                 if(SourceString[i+1] == '\0')   break;
929                 
930                 if('0' <= SourceString[i+1] && SourceString[i+1] <= '9')
931                         val |= (SourceString[i+1] - '0');
932                 else if('A' <= SourceString[i+1] && SourceString[i+1] <= 'F')
933                         val |= (SourceString[i+1] - 'A' + 10);
934                 else if('a' <= SourceString[i+1] && SourceString[i+1] <= 'f')
935                         val |= (SourceString[i+1] - 'a' + 10);
936                 
937                 Dest[i/2] = val;
938         }
939         return i/2;
940 }
941
942 Uint16 SwapEndian16(Uint16 Val)
943 {
944         return ((Val&0xFF)<<8) | ((Val>>8)&0xFF);
945 }
946 Uint32 SwapEndian32(Uint32 Val)
947 {
948         return ((Val&0xFF)<<24) | ((Val&0xFF00)<<8) | ((Val>>8)&0xFF00) | ((Val>>24)&0xFF);
949 }

UCC git Repository :: git.ucc.asn.au