efiemu.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2006,2007,2009 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* This is an emulation of EFI runtime services.
  19. This allows a more uniform boot on i386 machines.
  20. As it emulates only runtime serviceit isn't able
  21. to chainload EFI bootloader on non-EFI system (TODO) */
  22. #ifdef __i386__
  23. #include <grub/i386/types.h>
  24. #else
  25. #include <grub/x86_64/types.h>
  26. #endif
  27. #include <grub/symbol.h>
  28. #include <grub/types.h>
  29. #include <grub/efi/api.h>
  30. #include <grub/efiemu/runtime.h>
  31. grub_efi_status_t __grub_efi_api
  32. efiemu_get_time (grub_efi_time_t *time,
  33. grub_efi_time_capabilities_t *capabilities);
  34. grub_efi_status_t __grub_efi_api
  35. efiemu_set_time (grub_efi_time_t *time);
  36. grub_efi_status_t __grub_efi_api
  37. efiemu_get_wakeup_time (grub_efi_boolean_t *enabled,
  38. grub_efi_boolean_t *pending,
  39. grub_efi_time_t *time);
  40. grub_efi_status_t __grub_efi_api
  41. efiemu_set_wakeup_time (grub_efi_boolean_t enabled,
  42. grub_efi_time_t *time);
  43. #ifdef __APPLE__
  44. #define PHYSICAL_ATTRIBUTE __attribute__ ((section("_text-physical, _text-physical")));
  45. #else
  46. #define PHYSICAL_ATTRIBUTE __attribute__ ((section(".text-physical")));
  47. #endif
  48. grub_efi_status_t __grub_efi_api
  49. efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
  50. grub_efi_uintn_t descriptor_size,
  51. grub_efi_uint32_t descriptor_version,
  52. grub_efi_memory_descriptor_t *virtual_map)
  53. PHYSICAL_ATTRIBUTE;
  54. grub_efi_status_t __grub_efi_api
  55. efiemu_convert_pointer (grub_efi_uintn_t debug_disposition,
  56. void **address)
  57. PHYSICAL_ATTRIBUTE;
  58. grub_efi_status_t __grub_efi_api
  59. efiemu_get_variable (grub_efi_char16_t *variable_name,
  60. const grub_packed_guid_t *vendor_guid,
  61. grub_efi_uint32_t *attributes,
  62. grub_efi_uintn_t *data_size,
  63. void *data);
  64. grub_efi_status_t __grub_efi_api
  65. efiemu_get_next_variable_name (grub_efi_uintn_t *variable_name_size,
  66. grub_efi_char16_t *variable_name,
  67. grub_packed_guid_t *vendor_guid);
  68. grub_efi_status_t __grub_efi_api
  69. efiemu_set_variable (grub_efi_char16_t *variable_name,
  70. const grub_packed_guid_t *vendor_guid,
  71. grub_efi_uint32_t attributes,
  72. grub_efi_uintn_t data_size,
  73. void *data);
  74. grub_efi_status_t __grub_efi_api
  75. efiemu_get_next_high_monotonic_count (grub_efi_uint32_t *high_count);
  76. void __grub_efi_api
  77. efiemu_reset_system (grub_efi_reset_type_t reset_type,
  78. grub_efi_status_t reset_status,
  79. grub_efi_uintn_t data_size,
  80. grub_efi_char16_t *reset_data);
  81. grub_efi_status_t __grub_efi_api
  82. EFI_FUNC (efiemu_set_virtual_address_map) (grub_efi_uintn_t,
  83. grub_efi_uintn_t,
  84. grub_efi_uint32_t,
  85. grub_efi_memory_descriptor_t *)
  86. PHYSICAL_ATTRIBUTE;
  87. grub_efi_status_t __grub_efi_api
  88. EFI_FUNC (efiemu_convert_pointer) (grub_efi_uintn_t debug_disposition,
  89. void **address)
  90. PHYSICAL_ATTRIBUTE;
  91. static grub_uint32_t
  92. efiemu_getcrc32 (grub_uint32_t crc, void *buf, int size)
  93. PHYSICAL_ATTRIBUTE;
  94. static void
  95. init_crc32_table (void)
  96. PHYSICAL_ATTRIBUTE;
  97. static grub_uint32_t
  98. reflect (grub_uint32_t ref, int len)
  99. PHYSICAL_ATTRIBUTE;
  100. /*
  101. The log. It's used when examining memory dump
  102. */
  103. static grub_uint8_t loge[1000] = "EFIEMULOG";
  104. static int logn = 9;
  105. #define LOG(x) { if (logn<900) loge[logn++]=x; }
  106. /* Interface with grub */
  107. extern grub_uint8_t efiemu_ptv_relocated;
  108. struct grub_efi_runtime_services efiemu_runtime_services;
  109. struct grub_efi_system_table efiemu_system_table;
  110. extern struct grub_efiemu_ptv_rel efiemu_ptv_relloc[];
  111. extern grub_uint8_t efiemu_variables[];
  112. extern grub_uint32_t efiemu_varsize;
  113. extern grub_uint32_t efiemu_high_monotonic_count;
  114. extern grub_int16_t efiemu_time_zone;
  115. extern grub_uint8_t efiemu_time_daylight;
  116. extern grub_uint32_t efiemu_time_accuracy;
  117. /* Some standard functions because we need to be standalone */
  118. static void
  119. efiemu_memcpy (void *to, const void *from, int count)
  120. {
  121. int i;
  122. for (i = 0; i < count; i++)
  123. ((grub_uint8_t *) to)[i] = ((const grub_uint8_t *) from)[i];
  124. }
  125. static int
  126. efiemu_str16equal (grub_uint16_t *a, grub_uint16_t *b)
  127. {
  128. grub_uint16_t *ptr1, *ptr2;
  129. for (ptr1=a,ptr2=b; *ptr1 && *ptr2 == *ptr1; ptr1++, ptr2++);
  130. return *ptr2 == *ptr1;
  131. }
  132. static grub_size_t
  133. efiemu_str16len (grub_uint16_t *a)
  134. {
  135. grub_uint16_t *ptr1;
  136. for (ptr1 = a; *ptr1; ptr1++);
  137. return ptr1 - a;
  138. }
  139. static int
  140. efiemu_memequal (const void *a, const void *b, grub_size_t n)
  141. {
  142. grub_uint8_t *ptr1, *ptr2;
  143. for (ptr1 = (grub_uint8_t *) a, ptr2 = (grub_uint8_t *)b;
  144. ptr1 < (grub_uint8_t *)a + n && *ptr2 == *ptr1; ptr1++, ptr2++);
  145. return ptr1 == a + n;
  146. }
  147. static void
  148. efiemu_memset (grub_uint8_t *a, grub_uint8_t b, grub_size_t n)
  149. {
  150. grub_uint8_t *ptr1;
  151. for (ptr1=a; ptr1 < a + n; ptr1++)
  152. *ptr1 = b;
  153. }
  154. static inline void
  155. write_cmos (grub_uint8_t addr, grub_uint8_t val)
  156. {
  157. asm volatile ("outb %%al,$0x70\n"
  158. "mov %%cl, %%al\n"
  159. "outb %%al,$0x71": :"a" (addr), "c" (val));
  160. }
  161. static inline grub_uint8_t
  162. read_cmos (grub_uint8_t addr)
  163. {
  164. grub_uint8_t ret;
  165. asm volatile ("outb %%al, $0x70\n"
  166. "inb $0x71, %%al": "=a"(ret) :"a" (addr));
  167. return ret;
  168. }
  169. /* Needed by some gcc versions */
  170. int __stack_chk_fail ()
  171. {
  172. return 0;
  173. }
  174. /* The function that implement runtime services as specified in
  175. EFI specification */
  176. static inline grub_uint8_t
  177. bcd_to_hex (grub_uint8_t in)
  178. {
  179. return 10 * ((in & 0xf0) >> 4) + (in & 0x0f);
  180. }
  181. grub_efi_status_t __grub_efi_api
  182. EFI_FUNC (efiemu_get_time) (grub_efi_time_t *time,
  183. grub_efi_time_capabilities_t *capabilities)
  184. {
  185. LOG ('a');
  186. grub_uint8_t state;
  187. state = read_cmos (0xb);
  188. if (!(state & (1 << 2)))
  189. {
  190. time->year = 2000 + bcd_to_hex (read_cmos (0x9));
  191. time->month = bcd_to_hex (read_cmos (0x8));
  192. time->day = bcd_to_hex (read_cmos (0x7));
  193. time->hour = bcd_to_hex (read_cmos (0x4));
  194. if (time->hour >= 81)
  195. time->hour -= 80 - 12;
  196. if (time->hour == 24)
  197. time->hour = 0;
  198. time->minute = bcd_to_hex (read_cmos (0x2));
  199. time->second = bcd_to_hex (read_cmos (0x0));
  200. }
  201. else
  202. {
  203. time->year = 2000 + read_cmos (0x9);
  204. time->month = read_cmos (0x8);
  205. time->day = read_cmos (0x7);
  206. time->hour = read_cmos (0x4);
  207. if (time->hour >= 0x81)
  208. time->hour -= 0x80 - 12;
  209. if (time->hour == 24)
  210. time->hour = 0;
  211. time->minute = read_cmos (0x2);
  212. time->second = read_cmos (0x0);
  213. }
  214. time->nanosecond = 0;
  215. time->pad1 = 0;
  216. time->pad2 = 0;
  217. time->time_zone = efiemu_time_zone;
  218. time->daylight = efiemu_time_daylight;
  219. capabilities->resolution = 1;
  220. capabilities->accuracy = efiemu_time_accuracy;
  221. capabilities->sets_to_zero = 0;
  222. return GRUB_EFI_SUCCESS;
  223. }
  224. grub_efi_status_t __grub_efi_api
  225. EFI_FUNC (efiemu_set_time) (grub_efi_time_t *time)
  226. {
  227. LOG ('b');
  228. grub_uint8_t state;
  229. state = read_cmos (0xb);
  230. write_cmos (0xb, state | 0x6);
  231. write_cmos (0x9, time->year - 2000);
  232. write_cmos (0x8, time->month);
  233. write_cmos (0x7, time->day);
  234. write_cmos (0x4, time->hour);
  235. write_cmos (0x2, time->minute);
  236. write_cmos (0x0, time->second);
  237. efiemu_time_zone = time->time_zone;
  238. efiemu_time_daylight = time->daylight;
  239. return GRUB_EFI_SUCCESS;
  240. }
  241. /* Following 2 functions are vendor specific. So announce it as unsupported */
  242. grub_efi_status_t __grub_efi_api
  243. EFI_FUNC (efiemu_get_wakeup_time) (grub_efi_boolean_t *enabled,
  244. grub_efi_boolean_t *pending,
  245. grub_efi_time_t *time)
  246. {
  247. LOG ('c');
  248. return GRUB_EFI_UNSUPPORTED;
  249. }
  250. grub_efi_status_t __grub_efi_api
  251. EFI_FUNC (efiemu_set_wakeup_time) (grub_efi_boolean_t enabled,
  252. grub_efi_time_t *time)
  253. {
  254. LOG ('d');
  255. return GRUB_EFI_UNSUPPORTED;
  256. }
  257. static grub_uint32_t crc32_table [256];
  258. static grub_uint32_t
  259. reflect (grub_uint32_t ref, int len)
  260. {
  261. grub_uint32_t result = 0;
  262. int i;
  263. for (i = 1; i <= len; i++)
  264. {
  265. if (ref & 1)
  266. result |= 1 << (len - i);
  267. ref >>= 1;
  268. }
  269. return result;
  270. }
  271. static void
  272. init_crc32_table (void)
  273. {
  274. grub_uint32_t polynomial = 0x04c11db7;
  275. int i, j;
  276. for(i = 0; i < 256; i++)
  277. {
  278. crc32_table[i] = reflect(i, 8) << 24;
  279. for (j = 0; j < 8; j++)
  280. crc32_table[i] = (crc32_table[i] << 1) ^
  281. (crc32_table[i] & (1 << 31) ? polynomial : 0);
  282. crc32_table[i] = reflect(crc32_table[i], 32);
  283. }
  284. }
  285. static grub_uint32_t
  286. efiemu_getcrc32 (grub_uint32_t crc, void *buf, int size)
  287. {
  288. int i;
  289. grub_uint8_t *data = buf;
  290. if (! crc32_table[1])
  291. init_crc32_table ();
  292. crc^= 0xffffffff;
  293. for (i = 0; i < size; i++)
  294. {
  295. crc = (crc >> 8) ^ crc32_table[(crc & 0xFF) ^ *data];
  296. data++;
  297. }
  298. return crc ^ 0xffffffff;
  299. }
  300. grub_efi_status_t __grub_efi_api EFI_FUNC
  301. (efiemu_set_virtual_address_map) (grub_efi_uintn_t memory_map_size,
  302. grub_efi_uintn_t descriptor_size,
  303. grub_efi_uint32_t descriptor_version,
  304. grub_efi_memory_descriptor_t *virtual_map)
  305. {
  306. struct grub_efiemu_ptv_rel *cur_relloc;
  307. LOG ('e');
  308. /* Ensure that we are called only once */
  309. if (efiemu_ptv_relocated)
  310. return GRUB_EFI_UNSUPPORTED;
  311. efiemu_ptv_relocated = 1;
  312. /* Correct addresses using information supplied by grub */
  313. for (cur_relloc = efiemu_ptv_relloc; cur_relloc->size;cur_relloc++)
  314. {
  315. grub_int64_t corr = 0;
  316. grub_efi_memory_descriptor_t *descptr;
  317. /* Compute correction */
  318. for (descptr = virtual_map;
  319. ((grub_uint8_t *) descptr - (grub_uint8_t *) virtual_map)
  320. < memory_map_size;
  321. descptr = (grub_efi_memory_descriptor_t *)
  322. ((grub_uint8_t *) descptr + descriptor_size))
  323. {
  324. if (descptr->type == cur_relloc->plustype)
  325. corr += descptr->virtual_start - descptr->physical_start;
  326. if (descptr->type == cur_relloc->minustype)
  327. corr -= descptr->virtual_start - descptr->physical_start;
  328. }
  329. /* Apply correction */
  330. switch (cur_relloc->size)
  331. {
  332. case 8:
  333. *((grub_uint64_t *) (grub_addr_t) cur_relloc->addr) += corr;
  334. break;
  335. case 4:
  336. *((grub_uint32_t *) (grub_addr_t) cur_relloc->addr) += corr;
  337. break;
  338. case 2:
  339. *((grub_uint16_t *) (grub_addr_t) cur_relloc->addr) += corr;
  340. break;
  341. case 1:
  342. *((grub_uint8_t *) (grub_addr_t) cur_relloc->addr) += corr;
  343. break;
  344. }
  345. }
  346. /* Recompute crc32 of system table and runtime services */
  347. efiemu_system_table.hdr.crc32 = 0;
  348. efiemu_system_table.hdr.crc32 = efiemu_getcrc32
  349. (0, &efiemu_system_table, sizeof (efiemu_system_table));
  350. efiemu_runtime_services.hdr.crc32 = 0;
  351. efiemu_runtime_services.hdr.crc32 = efiemu_getcrc32
  352. (0, &efiemu_runtime_services, sizeof (efiemu_runtime_services));
  353. return GRUB_EFI_SUCCESS;
  354. }
  355. /* since efiemu_set_virtual_address_map corrects all the pointers
  356. we don't need efiemu_convert_pointer */
  357. grub_efi_status_t __grub_efi_api
  358. EFI_FUNC (efiemu_convert_pointer) (grub_efi_uintn_t debug_disposition,
  359. void **address)
  360. {
  361. LOG ('f');
  362. return GRUB_EFI_UNSUPPORTED;
  363. }
  364. /* Next comes variable services. Because we have no vendor-independent
  365. way to store these variables we have no non-volatility */
  366. /* Find variable by name and GUID. */
  367. static struct efi_variable *
  368. find_variable (const grub_packed_guid_t *vendor_guid,
  369. grub_efi_char16_t *variable_name)
  370. {
  371. grub_uint8_t *ptr;
  372. struct efi_variable *efivar;
  373. for (ptr = efiemu_variables; ptr < efiemu_variables + efiemu_varsize; )
  374. {
  375. efivar = (struct efi_variable *) ptr;
  376. if (!efivar->namelen)
  377. return 0;
  378. if (efiemu_str16equal((grub_efi_char16_t *)(efivar + 1), variable_name)
  379. && efiemu_memequal (&(efivar->guid), vendor_guid,
  380. sizeof (efivar->guid)))
  381. return efivar;
  382. ptr += efivar->namelen + efivar->size + sizeof (*efivar);
  383. }
  384. return 0;
  385. }
  386. grub_efi_status_t __grub_efi_api
  387. EFI_FUNC (efiemu_get_variable) (grub_efi_char16_t *variable_name,
  388. const grub_packed_guid_t *vendor_guid,
  389. grub_efi_uint32_t *attributes,
  390. grub_efi_uintn_t *data_size,
  391. void *data)
  392. {
  393. struct efi_variable *efivar;
  394. LOG ('g');
  395. efivar = find_variable (vendor_guid, variable_name);
  396. if (!efivar)
  397. return GRUB_EFI_NOT_FOUND;
  398. if (*data_size < efivar->size)
  399. {
  400. *data_size = efivar->size;
  401. return GRUB_EFI_BUFFER_TOO_SMALL;
  402. }
  403. *data_size = efivar->size;
  404. efiemu_memcpy (data, (grub_uint8_t *)(efivar + 1) + efivar->namelen,
  405. efivar->size);
  406. *attributes = efivar->attributes;
  407. return GRUB_EFI_SUCCESS;
  408. }
  409. grub_efi_status_t __grub_efi_api EFI_FUNC
  410. (efiemu_get_next_variable_name) (grub_efi_uintn_t *variable_name_size,
  411. grub_efi_char16_t *variable_name,
  412. grub_packed_guid_t *vendor_guid)
  413. {
  414. struct efi_variable *efivar;
  415. LOG ('l');
  416. if (!variable_name_size || !variable_name || !vendor_guid)
  417. return GRUB_EFI_INVALID_PARAMETER;
  418. if (variable_name[0])
  419. {
  420. efivar = find_variable (vendor_guid, variable_name);
  421. if (!efivar)
  422. return GRUB_EFI_NOT_FOUND;
  423. efivar = (struct efi_variable *)((grub_uint8_t *)efivar
  424. + efivar->namelen
  425. + efivar->size + sizeof (*efivar));
  426. }
  427. else
  428. efivar = (struct efi_variable *) (efiemu_variables);
  429. LOG ('m');
  430. if ((grub_uint8_t *)efivar >= efiemu_variables + efiemu_varsize
  431. || !efivar->namelen)
  432. return GRUB_EFI_NOT_FOUND;
  433. if (*variable_name_size < efivar->namelen)
  434. {
  435. *variable_name_size = efivar->namelen;
  436. return GRUB_EFI_BUFFER_TOO_SMALL;
  437. }
  438. efiemu_memcpy (variable_name, efivar + 1, efivar->namelen);
  439. efiemu_memcpy (vendor_guid, &(efivar->guid),
  440. sizeof (efivar->guid));
  441. LOG('h');
  442. return GRUB_EFI_SUCCESS;
  443. }
  444. grub_efi_status_t __grub_efi_api
  445. EFI_FUNC (efiemu_set_variable) (grub_efi_char16_t *variable_name,
  446. const grub_packed_guid_t *vendor_guid,
  447. grub_efi_uint32_t attributes,
  448. grub_efi_uintn_t data_size,
  449. void *data)
  450. {
  451. struct efi_variable *efivar;
  452. grub_uint8_t *ptr;
  453. LOG('i');
  454. if (!variable_name[0])
  455. return GRUB_EFI_INVALID_PARAMETER;
  456. efivar = find_variable (vendor_guid, variable_name);
  457. /* Delete variable if any */
  458. if (efivar)
  459. {
  460. efiemu_memcpy (efivar, (grub_uint8_t *)(efivar + 1)
  461. + efivar->namelen + efivar->size,
  462. (efiemu_variables + efiemu_varsize)
  463. - ((grub_uint8_t *)(efivar + 1)
  464. + efivar->namelen + efivar->size));
  465. efiemu_memset (efiemu_variables + efiemu_varsize
  466. - (sizeof (*efivar) + efivar->namelen + efivar->size),
  467. 0, (sizeof (*efivar) + efivar->namelen + efivar->size));
  468. }
  469. if (!data_size)
  470. return GRUB_EFI_SUCCESS;
  471. for (ptr = efiemu_variables; ptr < efiemu_variables + efiemu_varsize; )
  472. {
  473. efivar = (struct efi_variable *) ptr;
  474. ptr += efivar->namelen + efivar->size + sizeof (*efivar);
  475. if (!efivar->namelen)
  476. break;
  477. }
  478. if ((grub_uint8_t *)(efivar + 1) + data_size
  479. + 2 * (efiemu_str16len (variable_name) + 1)
  480. >= efiemu_variables + efiemu_varsize)
  481. return GRUB_EFI_OUT_OF_RESOURCES;
  482. efiemu_memcpy (&(efivar->guid), vendor_guid, sizeof (efivar->guid));
  483. efivar->namelen = 2 * (efiemu_str16len (variable_name) + 1);
  484. efivar->size = data_size;
  485. efivar->attributes = attributes;
  486. efiemu_memcpy (efivar + 1, variable_name,
  487. 2 * (efiemu_str16len (variable_name) + 1));
  488. efiemu_memcpy ((grub_uint8_t *)(efivar + 1)
  489. + 2 * (efiemu_str16len (variable_name) + 1),
  490. data, data_size);
  491. return GRUB_EFI_SUCCESS;
  492. }
  493. grub_efi_status_t __grub_efi_api EFI_FUNC
  494. (efiemu_get_next_high_monotonic_count) (grub_efi_uint32_t *high_count)
  495. {
  496. LOG ('j');
  497. if (!high_count)
  498. return GRUB_EFI_INVALID_PARAMETER;
  499. *high_count = ++efiemu_high_monotonic_count;
  500. return GRUB_EFI_SUCCESS;
  501. }
  502. /* To implement it with APM we need to go to real mode. It's too much hassle
  503. Besides EFI specification says that this function shouldn't be used
  504. on systems supporting ACPI
  505. */
  506. void __grub_efi_api
  507. EFI_FUNC (efiemu_reset_system) (grub_efi_reset_type_t reset_type,
  508. grub_efi_status_t reset_status,
  509. grub_efi_uintn_t data_size,
  510. grub_efi_char16_t *reset_data)
  511. {
  512. LOG ('k');
  513. }
  514. struct grub_efi_runtime_services efiemu_runtime_services =
  515. {
  516. .hdr =
  517. {
  518. .signature = GRUB_EFIEMU_RUNTIME_SERVICES_SIGNATURE,
  519. .revision = 0x0001000a,
  520. .header_size = sizeof (struct grub_efi_runtime_services),
  521. .crc32 = 0, /* filled later*/
  522. .reserved = 0
  523. },
  524. .get_time = efiemu_get_time,
  525. .set_time = efiemu_set_time,
  526. .get_wakeup_time = efiemu_get_wakeup_time,
  527. .set_wakeup_time = efiemu_set_wakeup_time,
  528. .set_virtual_address_map = efiemu_set_virtual_address_map,
  529. .convert_pointer = efiemu_convert_pointer,
  530. /*
  531. The code is structured in a way to accept unaligned inputs
  532. in most cases and supply 4-byte aligned outputs.
  533. Efiemu case is a bit ugly because there inputs and outputs are
  534. reversed and so we need careful casts to account for this
  535. inversion.
  536. */
  537. .get_variable = (grub_efi_status_t
  538. (__grub_efi_api *) (grub_efi_char16_t *variable_name,
  539. const grub_guid_t *vendor_guid,
  540. grub_efi_uint32_t *attributes,
  541. grub_efi_uintn_t *data_size,
  542. void *data)) efiemu_get_variable,
  543. .get_next_variable_name = (grub_efi_status_t
  544. (__grub_efi_api *) (grub_efi_uintn_t *variable_name_size,
  545. grub_efi_char16_t *variable_name,
  546. grub_guid_t *vendor_guid)) efiemu_get_next_variable_name,
  547. .set_variable = (grub_efi_status_t
  548. (__grub_efi_api *) (grub_efi_char16_t *variable_name,
  549. const grub_guid_t *vendor_guid,
  550. grub_efi_uint32_t attributes,
  551. grub_efi_uintn_t data_size,
  552. void *data)) efiemu_set_variable,
  553. .get_next_high_monotonic_count = efiemu_get_next_high_monotonic_count,
  554. .reset_system = efiemu_reset_system
  555. };
  556. static grub_uint16_t efiemu_vendor[] =
  557. {'G', 'R', 'U', 'B', ' ', 'E', 'F', 'I', ' ',
  558. 'R', 'U', 'N', 'T', 'I', 'M', 'E', 0};
  559. struct grub_efi_system_table efiemu_system_table =
  560. {
  561. .hdr =
  562. {
  563. .signature = GRUB_EFIEMU_SYSTEM_TABLE_SIGNATURE,
  564. .revision = 0x0001000a,
  565. .header_size = sizeof (struct grub_efi_system_table),
  566. .crc32 = 0, /* filled later*/
  567. .reserved = 0
  568. },
  569. .firmware_vendor = efiemu_vendor,
  570. .firmware_revision = 0x0001000a,
  571. .console_in_handler = 0,
  572. .con_in = 0,
  573. .console_out_handler = 0,
  574. .con_out = 0,
  575. .standard_error_handle = 0,
  576. .std_err = 0,
  577. .runtime_services = &efiemu_runtime_services,
  578. .boot_services = 0,
  579. .num_table_entries = 0,
  580. .configuration_table = 0
  581. };