]> code.delx.au - refind/blob - filesystems/fsw_efi_lib.c
Improvements to refind-mkdefault, including packaging files.
[refind] / filesystems / fsw_efi_lib.c
1 /**
2 * \file fsw_efi_lib.c
3 * EFI host environment library functions.
4 */
5
6 /*-
7 * Copyright (c) 2006 Christoph Pfisterer
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are
11 * met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the
19 * distribution.
20 *
21 * * Neither the name of Christoph Pfisterer nor the names of the
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #include "fsw_efi.h"
39
40
41 //
42 // time conversion
43 //
44 // Adopted from public domain code in FreeBSD libc.
45 //
46
47 #define SECSPERMIN 60
48 #define MINSPERHOUR 60
49 #define HOURSPERDAY 24
50 #define DAYSPERWEEK 7
51 #define DAYSPERNYEAR 365
52 #define DAYSPERLYEAR 366
53 #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
54 #define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
55 #define MONSPERYEAR 12
56
57 #define EPOCH_YEAR 1970
58 #define EPOCH_WDAY TM_THURSDAY
59
60 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
61 #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
62
63 static const int mon_lengths[2][MONSPERYEAR] = {
64 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
65 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
66 };
67 static const int year_lengths[2] = {
68 DAYSPERNYEAR, DAYSPERLYEAR
69 };
70
71 VOID fsw_efi_decode_time(OUT EFI_TIME *EfiTime, IN UINT32 UnixTime)
72 {
73 long days, rem;
74 int y, newy, yleap;
75 const int *ip;
76
77 ZeroMem(EfiTime, sizeof(EFI_TIME));
78
79 days = UnixTime / SECSPERDAY;
80 rem = UnixTime % SECSPERDAY;
81
82 EfiTime->Hour = (UINT8) (rem / SECSPERHOUR);
83 rem = rem % SECSPERHOUR;
84 EfiTime->Minute = (UINT8) (rem / SECSPERMIN);
85 EfiTime->Second = (UINT8) (rem % SECSPERMIN);
86
87 y = EPOCH_YEAR;
88 while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
89 newy = y + days / DAYSPERNYEAR;
90 if (days < 0)
91 --newy;
92 days -= (newy - y) * DAYSPERNYEAR +
93 LEAPS_THRU_END_OF(newy - 1) -
94 LEAPS_THRU_END_OF(y - 1);
95 y = newy;
96 }
97 EfiTime->Year = (UINT16)y;
98 ip = mon_lengths[yleap];
99 for (EfiTime->Month = 0; days >= (long) ip[EfiTime->Month]; ++(EfiTime->Month))
100 days = days - (long) ip[EfiTime->Month];
101 EfiTime->Month++; // adjust range to EFI conventions
102 EfiTime->Day = (UINT8) (days + 1);
103 }
104
105 //
106 // String functions, used for file and volume info
107 //
108
109 UINTN fsw_efi_strsize(struct fsw_string *s)
110 {
111 if (s->type == FSW_STRING_TYPE_EMPTY)
112 return sizeof(CHAR16);
113 return (s->len + 1) * sizeof(CHAR16);
114 }
115
116 VOID fsw_efi_strcpy(CHAR16 *Dest, struct fsw_string *src)
117 {
118 if (src->type == FSW_STRING_TYPE_EMPTY | src->size == 0) {
119 Dest[0] = 0;
120 } else if (src->type == FSW_STRING_TYPE_UTF16) {
121 CopyMem(Dest, src->data, src->size);
122 Dest[src->len] = 0;
123 } else {
124 // TODO: coerce, recurse
125 Dest[0] = 0;
126 }
127 }
128
129 // EOF