1 /*
2 * Copyright 2007-2013, Axel Dörfler, axeld@pinc-software.de.
3 * Copyright 2009, Michael Lotz, mmlr@mlotz.ch. All rights reserved.
4 *
5 * Distributed under the terms of the MIT License.
6 */
7
8
9 #include "utility.h"
10
11 #include <string.h>
12
13 #ifndef _BOOT_MODE
14 # include <utf8_functions.h>
15 #endif
16
17 #include "gpt_known_guids.h"
18
19
20 const guid_t kEmptyGUID = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
21
22
23 static void
put_utf8_byte(char * & to,size_t & left,char c)24 put_utf8_byte(char*& to, size_t& left, char c)
25 {
26 if (left <= 1)
27 return;
28
29 *(to++) = c;
30 left--;
31 }
32
33
34 // #pragma mark -
35
36
37 size_t
to_utf8(const uint16 * from,size_t maxFromLength,char * to,size_t toSize)38 to_utf8(const uint16* from, size_t maxFromLength, char* to, size_t toSize)
39 {
40 const char* start = to;
41 for (uint32 i = 0; i < maxFromLength; i++) {
42 // Decoding UTF-16LE
43 uint32 c = 0;
44 uint16 w1 = B_LENDIAN_TO_HOST_INT16(from[i]);
45 if (!w1)
46 break;
47
48 bool valid = false;
49 if (w1 < 0xD800 || w1 > 0xDFFF) {
50 c = w1;
51 valid = true;
52 }
53
54 if (!valid && (w1 >= 0xD800 && w1 <= 0xDBFF)) {
55 if (i + 1 < maxFromLength) {
56 uint16 w2 = B_LENDIAN_TO_HOST_INT16(from[i + 1]);
57 if (w2 >= 0xDC00 && w2 <= 0xDFFF) {
58 c = ((w1 & 0x3FF) << 10) | (w2 & 0x3FF);
59 c += 0x10000;
60 ++i;
61 valid = true;
62 }
63 }
64 }
65
66 if (!valid) break;
67
68 if (c < 0x80)
69 put_utf8_byte(to, toSize, c);
70 else if (c < 0x800) {
71 put_utf8_byte(to, toSize, 0xc0 | (c >> 6));
72 put_utf8_byte(to, toSize, 0x80 | (c & 0x3f));
73 } else if (c < 0x10000) {
74 put_utf8_byte(to, toSize, 0xe0 | (c >> 12));
75 put_utf8_byte(to, toSize, 0x80 | ((c >> 6) & 0x3f));
76 put_utf8_byte(to, toSize, 0x80 | (c & 0x3f));
77 } else if (c <= 0x10ffff) {
78 put_utf8_byte(to, toSize, 0xf0 | (c >> 18));
79 put_utf8_byte(to, toSize, 0x80 | ((c >> 12) & 0x3f));
80 put_utf8_byte(to, toSize, 0x80 | ((c >> 6) & 0x3f));
81 put_utf8_byte(to, toSize, 0x80 | (c & 0x3f));
82 }
83 }
84
85 if (toSize > 0)
86 *to++ = '\0';
87
88 return to - start;
89 }
90
91
92 #ifndef _BOOT_MODE
93 size_t
to_ucs2(const char * from,size_t fromLength,uint16 * to,size_t maxToLength)94 to_ucs2(const char* from, size_t fromLength, uint16* to, size_t maxToLength)
95 {
96 size_t index = 0;
97 while (from[0] != '\0' && index < maxToLength) {
98 uint32 c = UTF8ToCharCode(&from);
99
100 // Encoding UTF-16LE
101 if (c > 0x10FFFF) break; // invalid
102 if (c < 0x10000) {
103 to[index++] = B_HOST_TO_LENDIAN_INT16(c);
104 } else {
105 if (index + 1 >= maxToLength) break;
106 uint32 c2 = c - 0x10000;
107 uint16 w1 = 0xD800, w2 = 0xDC00;
108 w1 = w1 + ((c2 >> 10) & 0x3FF);
109 w2 = w2 + (c2 & 0x3FF);
110 to[index++] = B_HOST_TO_LENDIAN_INT16(w1);
111 to[index++] = B_HOST_TO_LENDIAN_INT16(w2);
112 }
113 }
114
115 if (index < maxToLength)
116 to[index++] = '\0';
117
118 return index;
119 }
120 #endif // !_BOOT_MODE
121
122
123 const char*
get_partition_type(const guid_t & guid)124 get_partition_type(const guid_t& guid)
125 {
126 for (uint32 i = 0; i < sizeof(kTypeMap) / sizeof(kTypeMap[0]); i++) {
127 if (kTypeMap[i].guid == guid)
128 return kTypeMap[i].type;
129 }
130
131 return NULL;
132 }
133
134
135 #ifndef _BOOT_MODE
136 bool
get_guid_for_partition_type(const char * type,guid_t & guid)137 get_guid_for_partition_type(const char* type, guid_t& guid)
138 {
139 for (uint32 i = 0; i < sizeof(kTypeMap) / sizeof(kTypeMap[0]); i++) {
140 if (strcmp(kTypeMap[i].type, type) == 0) {
141 guid = kTypeMap[i].guid;
142 return true;
143 }
144 }
145
146 return false;
147 }
148 #endif // !_BOOT_MODE
149