56c8efb6d98a7ca99197cb5f9308bbf27bdecdb8
[external/syslinux.git] / com32 / sysdump / ctime.c
1 #include <com32.h>
2 #include <string.h>
3 #include "ctime.h"
4
5 static uint8_t frombcd(uint8_t v)
6 {
7     uint8_t a = v & 0x0f;
8     uint8_t b = v >> 4;
9
10     return a + b*10;
11 }
12
13 uint32_t posix_time(void)
14 {
15     /* Days from March 1 for a specific month, starting in March */
16     static const unsigned int yday[12] =
17         { 0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337 };
18     com32sys_t ir, d0, d1, t0;
19     unsigned int c, y, mo, d, h, m, s;
20     uint32_t t;
21
22     memset(&ir, 0, sizeof ir);
23
24     ir.eax.b[1] = 0x04;
25     __intcall(0x1A, &ir, &d0);
26
27     ir.eax.b[1] = 0x02;
28     __intcall(0x1A, &ir, &t0);
29
30     ir.eax.b[1] = 0x04;
31     __intcall(0x1A, &ir, &d1);
32
33     if (t0.ecx.b[1] < 0x12)
34         d0 = d1;
35
36     c  = frombcd(d0.ecx.b[1]);
37     y  = frombcd(d0.ecx.b[0]);
38     mo = frombcd(d0.edx.b[1]);
39     d  = frombcd(d0.edx.b[0]);
40
41     h  = frombcd(t0.ecx.b[1]);
42     m  = frombcd(t0.ecx.b[0]);
43     s  = frombcd(t0.edx.b[1]);
44
45     /* We of course have no idea about the timezone, so ignore it */
46
47     /*
48      * Look for impossible dates... this code was written in 2010, so
49      * assume any century less than 20 is just broken.
50      */
51     if (c < 20)
52         c = 20;
53     y += c*100;
54
55     /* Consider Jan and Feb as the last months of the previous year */
56     if (mo < 3) {
57         y--;
58         mo += 12;
59     }
60
61     /*
62      * Just in case: if the month is nonsense, don't read off the end
63      * of the table...
64      */
65     if (mo-3 > 11)
66         return 0;
67
68     t = y*365 + y/4 - y/100 + y/400 + yday[mo-3] + d - 719469;
69     t *= 24;
70     t += h;
71     t *= 60;
72     t += m;
73     t *= 60;
74     t += s;
75
76     return t;
77 }