Imported Debian patch 0.5.4-1
[debian/efibootmgr] / src / lib / efi.c
1 /*
2   efivars_proc.[ch] - Manipulates EFI variables as exported in /proc/efi/vars
3
4   Copyright (C) 2001,2003 Dell Computer Corporation <Matt_Domsch@dell.com>
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <ctype.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <stdint.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <limits.h>
30 #include <unistd.h>
31 #include <dirent.h>
32 #include <sys/socket.h>
33 #include <sys/types.h>
34 #include <sys/ioctl.h>
35 #include <linux/sockios.h>
36 #include <linux/types.h>
37 #include <net/if.h>
38 #include <pci/pci.h>
39 #include <asm/types.h>
40 #include <linux/ethtool.h>
41 #include "efi.h"
42 #include "efichar.h"
43 #include "scsi_ioctls.h"
44 #include "disk.h"
45 #include "efibootmgr.h"
46 #include "efivars_procfs.h"
47 #include "efivars_sysfs.h"
48 #include "list.h"
49
50 static struct efivar_kernel_calls *fs_kernel_calls;
51
52 EFI_DEVICE_PATH *
53 load_option_path(EFI_LOAD_OPTION *option)
54 {
55         char *p = (char *) option;
56         return (EFI_DEVICE_PATH *)
57                 (p + sizeof(uint32_t) /* Attributes */
58                  + sizeof(uint16_t)   /* FilePathListLength*/
59                  + efichar_strsize(option->description)); /* Description */
60 }
61
62 char *
63 efi_guid_unparse(efi_guid_t *guid, char *out)
64 {
65         sprintf(out, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
66                 guid->b[3], guid->b[2], guid->b[1], guid->b[0],
67                 guid->b[5], guid->b[4], guid->b[7], guid->b[6],
68                 guid->b[8], guid->b[9], guid->b[10], guid->b[11],
69                 guid->b[12], guid->b[13], guid->b[14], guid->b[15]);
70         return out;
71 }
72
73 void
74 set_fs_kernel_calls()
75 {
76         char name[PATH_MAX];
77         DIR *dir;
78         snprintf(name, PATH_MAX, "%s", SYSFS_DIR_EFI_VARS);
79         dir = opendir(name);
80         if (dir) {
81                 closedir(dir);
82                 fs_kernel_calls = &sysfs_kernel_calls;
83                 return;
84         }
85
86         snprintf(name, PATH_MAX, "%s", PROCFS_DIR_EFI_VARS);
87         dir = opendir(name);
88         if (dir) {
89                 closedir(dir);
90                 fs_kernel_calls = &procfs_kernel_calls;
91                 return;
92         }
93         fprintf(stderr, "Fatal: Couldn't open either sysfs or procfs directories for accessing EFI variables.\n");
94         fprintf(stderr, "Try 'modprobe efivars' as root.\n");
95         exit(1);
96 }
97
98
99
100 static efi_status_t
101 write_variable_to_file(efi_variable_t *var)
102 {
103         int fd, byteswritten;
104         if (!var || !opts.testfile) return EFI_INVALID_PARAMETER;
105
106         printf("Test mode: Writing to %s\n", opts.testfile);
107         fd = creat(opts.testfile, S_IRWXU);
108         if (fd == -1) {
109                 perror("Couldn't write to testfile");
110                 return EFI_INVALID_PARAMETER;
111         }
112
113         byteswritten = write(fd, var, sizeof(*var));
114         if (byteswritten == -1) {
115                 perror("Writing to testfile");
116
117         }
118         close(fd);
119         return EFI_SUCCESS;
120 }
121
122 efi_status_t
123 read_variable(const char *name, efi_variable_t *var)
124 {
125         if (!name || !var) return EFI_INVALID_PARAMETER;
126         return fs_kernel_calls->read(name, var);
127 }
128
129 efi_status_t
130 create_variable(efi_variable_t *var)
131 {
132         if (!var) return EFI_INVALID_PARAMETER;
133         if (opts.testfile) return write_variable_to_file(var);
134         return fs_kernel_calls->create(var);
135 }
136
137 efi_status_t
138 delete_variable(efi_variable_t *var)
139 {
140         if (!var) return EFI_INVALID_PARAMETER;
141         if (opts.testfile) return write_variable_to_file(var);
142         return fs_kernel_calls->delete(var);
143 }
144
145
146 efi_status_t
147 edit_variable(efi_variable_t *var)
148 {
149         char name[PATH_MAX];
150         if (!var) return EFI_INVALID_PARAMETER;
151         if (opts.testfile) return write_variable_to_file(var);
152
153         variable_to_name(var, name);
154         return fs_kernel_calls->edit(name, var);
155 }
156
157 efi_status_t
158 create_or_edit_variable(efi_variable_t *var)
159 {
160         efi_variable_t testvar;
161         char name[PATH_MAX];
162
163         memcpy(&testvar, var, sizeof(*var));
164         variable_to_name(var, name);
165
166         if (read_variable(name, &testvar) == EFI_SUCCESS)
167                 return edit_variable(var);
168         else
169                 return create_variable(var);
170 }
171
172 static int
173 select_boot_var_names(const struct dirent *d)
174 {
175         if (!strncmp(d->d_name, "Boot", 4) &&
176             isxdigit(d->d_name[4]) && isxdigit(d->d_name[5]) &&
177             isxdigit(d->d_name[6]) && isxdigit(d->d_name[7]) &&
178             d->d_name[8] == '-')
179                 return 1;
180         return 0;
181 }
182
183 int
184 read_boot_var_names(struct dirent ***namelist)
185 {
186         if (!fs_kernel_calls || !namelist) return -1;
187         return scandir(fs_kernel_calls->path,
188                        namelist, select_boot_var_names,
189                        alphasort);
190 }
191
192
193 static int
194 get_edd_version()
195 {
196         efi_status_t status;
197         efi_variable_t var;
198         efi_guid_t guid = BLKX_UNKNOWN_GUID;
199         char name[80], text_guid[40];
200         ACPI_DEVICE_PATH *path = (ACPI_DEVICE_PATH *)&(var.Data);
201         int rc = 0;
202
203         /* Allow global user option override */
204
205         switch (opts.edd_version)
206         {
207         case 0: /* No EDD information */
208                 return 0;
209                 break;
210         case 1: /* EDD 1.0 */
211                 return 1;
212                 break;
213         case 3: /* EDD 3.0 */
214                 return 3;
215                 break;
216         default:
217                 break;
218         }
219
220
221         memset(&var, 0, sizeof(efi_variable_t));
222         efi_guid_unparse(&guid, text_guid);
223         sprintf(name, "blk0-%s", text_guid);
224
225         status = read_variable(name, &var);
226         if (status != EFI_SUCCESS) {
227                 return 0;
228         }
229         if (path->type == 2 && path->subtype == 1) rc = 3;
230         else rc = 1;
231         return rc;
232 }
233
234 /*
235   EFI_DEVICE_PATH, 0x01 (Hardware), 0x04 (Vendor), length 0x0018
236   This needs to know what EFI device has the boot device.
237 */
238 static uint16_t
239 make_edd10_device_path(void *dest, uint32_t hardware_device)
240 {
241         VENDOR_DEVICE_PATH *hw;
242         char buffer[EDD10_HARDWARE_VENDOR_PATH_LENGTH];
243         efi_guid_t guid = EDD10_HARDWARE_VENDOR_PATH_GUID;
244         uint32_t *data;
245         memset(buffer, 0, sizeof(buffer));
246         hw = (VENDOR_DEVICE_PATH *)buffer;
247         data = (uint32_t *)hw->data;
248         hw->type = 0x01; /* Hardware Device Path */
249         hw->subtype = 0x04; /* Vendor */
250         hw->length = EDD10_HARDWARE_VENDOR_PATH_LENGTH;
251         memcpy(&(hw->vendor_guid), &guid, sizeof(guid));
252         *data = hardware_device;
253         memcpy(dest, buffer, hw->length);
254         return hw->length;
255 }
256
257 static uint16_t
258 make_end_device_path(void *dest)
259 {
260         END_DEVICE_PATH p;
261         memset(&p, 0, sizeof(p));
262         p.type = 0x7F; /* End of Hardware Device Path */
263         p.subtype = 0xFF; /* End Entire Device Path */
264         p.length = sizeof(p);
265         memcpy(dest, &p, p.length);
266         return p.length;
267 }
268
269 static uint16_t
270 make_acpi_device_path(void *dest, uint32_t _HID, uint32_t _UID)
271 {
272         ACPI_DEVICE_PATH p;
273         memset(&p, 0, sizeof(p));
274         p.type = 2;
275         p.subtype = 1;
276         p.length = sizeof(p);
277         p._HID = _HID;
278         p._UID = _UID;
279         memcpy(dest, &p, p.length);
280         return p.length;
281 }
282
283 static uint16_t
284 make_mac_addr_device_path(void *dest, char *mac, uint8_t iftype)
285 {
286
287         int i;
288         MAC_ADDR_DEVICE_PATH p;
289         memset(&p, 0, sizeof(p));
290         p.type = 3;
291         p.subtype = 11;
292         p.length = sizeof(p);
293         for (i=0; i < 14; i++) {
294                 p.macaddr[i] = mac[i];
295         }
296         p.iftype = iftype;
297         memcpy(dest, &p, p.length);
298         return p.length;
299 }
300
301 struct device
302 {
303         struct pci_dev *pci_dev;
304         struct list_head node;
305 };
306
307 static struct device *
308 is_parent_bridge(struct pci_dev *p, unsigned int target_bus)
309 {
310         struct device *d;
311         unsigned int primary, secondary;
312
313         if ( (pci_read_word(p, PCI_HEADER_TYPE) & 0x7f) != PCI_HEADER_TYPE_BRIDGE)
314                 return NULL;
315
316         primary=pci_read_byte(p, PCI_PRIMARY_BUS);
317         secondary=pci_read_byte(p, PCI_SECONDARY_BUS);
318
319
320         if (secondary != target_bus)
321                 return NULL;
322
323         d = malloc(sizeof(struct device));
324         if (!d)
325                 return NULL;
326         memset(d, 0, sizeof(*d));
327         INIT_LIST_HEAD(&d->node);
328
329         d->pci_dev = p;
330
331         return d;
332 }
333
334 static struct device *
335 find_parent(struct pci_access *pacc, unsigned int target_bus)
336 {
337         struct device *dev;
338         struct pci_dev *p;
339
340         for (p=pacc->devices; p; p=p->next) {
341                 dev = is_parent_bridge(p, target_bus);
342                 if (dev)
343                         return dev;
344         }
345         return NULL;
346 }
347
348 static uint16_t
349 make_one_pci_device_path(void *dest, uint8_t device, uint8_t function)
350 {
351         PCI_DEVICE_PATH p;
352         memset(&p, 0, sizeof(p));
353         p.type = 1;
354         p.subtype = 1;
355         p.length   = sizeof(p);
356         p.device   = device;
357         p.function = function;
358         memcpy(dest, &p, p.length);
359         return p.length;
360 }
361
362 static uint16_t
363 make_pci_device_path(void *dest, uint8_t bus, uint8_t device, uint8_t function)
364 {
365         struct device *dev;
366         struct pci_access *pacc;
367         struct list_head *pos, *n;
368         LIST_HEAD(pci_parent_list);
369         char *p = dest;
370
371         pacc = pci_alloc();
372         if (!pacc)
373                 return 0;
374
375         pci_init(pacc);
376         pci_scan_bus(pacc);
377
378         do {
379                 dev = find_parent(pacc, bus);
380                 if (dev) {
381                         list_add(&pci_parent_list, &dev->node);
382                         bus = dev->pci_dev->bus;
383                 }
384         } while (dev && bus);
385
386
387         list_for_each_safe(pos, n, &pci_parent_list) {
388                 dev = list_entry(pos, struct device, node);
389                 p += make_one_pci_device_path(p,
390                                               dev->pci_dev->dev,
391                                               dev->pci_dev->func);
392                 list_del(&dev->node);
393                 free(dev);
394         }
395
396         p += make_one_pci_device_path(p, device, function);
397
398         pci_cleanup(pacc);
399
400         return ((void *)p - dest);
401 }
402
403 static uint16_t
404 make_scsi_device_path(void *dest, uint16_t id, uint16_t lun)
405 {
406         SCSI_DEVICE_PATH p;
407         memset(&p, 0, sizeof(p));
408         p.type = 3;
409         p.subtype = 2;
410         p.length   = sizeof(p);
411         p.id       = id;
412         p.lun      = lun;
413         memcpy(dest, &p, p.length);
414         return p.length;
415 }
416
417 static uint16_t
418 make_harddrive_device_path(void *dest, uint32_t num, uint64_t start, uint64_t size,
419                            uint8_t *signature,
420                            uint8_t mbr_type, uint8_t signature_type)
421 {
422         HARDDRIVE_DEVICE_PATH p;
423         memset(&p, 0, sizeof(p));
424         p.type = 4;
425         p.subtype = 1;
426         p.length   = sizeof(p);
427         p.part_num = num;
428         p.start = start;
429         p.size = size;
430         if (signature) memcpy(p.signature, signature, 16);
431         p.mbr_type = mbr_type;
432         p.signature_type = signature_type;
433         memcpy(dest, &p, p.length);
434         return p.length;
435 }
436
437 static uint16_t
438 make_file_path_device_path(void *dest, efi_char16_t *name)
439 {
440         FILE_PATH_DEVICE_PATH *p;
441         char buffer[1024];
442         int namelen  = efichar_strlen(name, -1);
443         int namesize = efichar_strsize(name);
444
445         memset(buffer, 0, sizeof(buffer));
446         p = (FILE_PATH_DEVICE_PATH *)buffer;
447         p->type      = 4;
448         p->subtype   = 4;
449         p->length    = 4 + namesize;
450         efichar_strncpy(p->path_name,
451                         name, namelen);
452
453         memcpy(dest, buffer, p->length);
454         return p->length;
455
456 }
457
458
459
460 static long
461 make_edd30_device_path(int fd, void *buffer)
462 {
463         int rc=0;
464         unsigned char bus=0, device=0, function=0;
465         Scsi_Idlun idlun;
466         unsigned char host=0, channel=0, id=0, lun=0;
467         char *p = buffer;
468
469
470         rc = disk_get_pci(fd, &bus, &device, &function);
471         if (rc) return 0;
472
473         memset(&idlun, 0, sizeof(idlun));
474         rc = get_scsi_idlun(fd, &idlun);
475         if (rc) return 0;
476         idlun_to_components(&idlun, &host, &channel, &id, &lun);
477
478         p += make_acpi_device_path      (p, EISAID_PNP0A03, bus);
479         p += make_pci_device_path       (p, bus, device, function);
480         p += make_scsi_device_path      (p, id, lun);
481         return ((void *)p - buffer);
482 }
483
484 /**
485  * make_disk_load_option()
486  * @disk disk
487  *
488  * Returns 0 on error, length of load option created on success.
489  */
490 char *make_disk_load_option(char *p, char *disk)
491 {
492     int disk_fd=0;
493     char buffer[80];
494     char signature[16];
495     int rc, edd_version=0;
496     uint8_t mbr_type=0, signature_type=0;
497     uint64_t start=0, size=0;
498     efi_char16_t os_loader_path[40];
499
500     memset(signature, 0, sizeof(signature));
501
502     disk_fd = open(opts.disk, O_RDWR);
503     if (disk_fd == -1) {
504         sprintf(buffer, "Could not open disk %s", opts.disk);
505         perror(buffer);
506         return 0;
507     }
508
509     if (opts.edd_version) {
510         edd_version = get_edd_version();
511
512         if (edd_version == 3) {
513             p += make_edd30_device_path(disk_fd, p);
514         }
515         else if (edd_version == 1) {
516             p += make_edd10_device_path(p, opts.edd10_devicenum);
517         }
518     }
519
520     rc = disk_get_partition_info (disk_fd, opts.part,
521                                   &start, &size, signature,
522                                   &mbr_type, &signature_type);
523
524     close(disk_fd);
525
526     if (rc) {
527         fprintf(stderr, "Error: no partition information on disk %s.\n"
528                 "       Cowardly refusing to create a boot option.\n",
529                 opts.disk);
530         return 0;
531     }
532
533     p += make_harddrive_device_path (p, opts.part,
534                                      start, size,
535                                      signature,
536                                      mbr_type, signature_type);
537
538     efichar_from_char(os_loader_path, opts.loader, sizeof(os_loader_path));
539     p += make_file_path_device_path (p, os_loader_path);
540     p += make_end_device_path       (p);
541
542     return(p);
543 }
544
545 /**
546  * make_net_load_option()
547  * @data - load option returned
548  *
549  * Returns NULL on error, or p advanced by length of load option
550  * created on success.
551  */
552 char *make_net_load_option(char *p, char *iface)
553 {
554     /* copied pretty much verbatim from the ethtool source */
555     int fd = 0, err; 
556     int bus, slot, func;
557     struct ifreq ifr;
558     struct ethtool_drvinfo drvinfo;
559
560     memset(&ifr, 0, sizeof(ifr));
561     strcpy(ifr.ifr_name, iface);
562     drvinfo.cmd = ETHTOOL_GDRVINFO;
563     ifr.ifr_data = (caddr_t)&drvinfo;
564     /* Open control socket */
565     fd = socket(AF_INET, SOCK_DGRAM, 0);
566     if (fd < 0) {
567         perror("Cannot get control socket");
568         goto out;
569     }
570     err = ioctl(fd, SIOCETHTOOL, &ifr);
571     if (err < 0) {
572         perror("Cannot get driver information");
573         goto out;
574     }
575
576     /* The domain part was added in 2.6 kernels.  Test for that first. */
577     err = sscanf(drvinfo.bus_info, "%*x:%2x:%2x.%x", &bus, &slot, &func);
578     if (err != 3) {
579             err = sscanf(drvinfo.bus_info, "%2x:%2x.%x", &bus, &slot, &func);
580             if (err != 3) {
581                     perror("Couldn't parse device location string.");
582                     goto out;
583             }
584     }
585
586     err = ioctl(fd, SIOCGIFHWADDR, &ifr);
587     if (err < 0) {
588         perror("Cannot get hardware address.");
589         goto out;
590     }
591
592     p += make_acpi_device_path(p, opts.acpi_hid, opts.acpi_uid);
593     p += make_pci_device_path(p, bus, (uint8_t)slot, (uint8_t)func);
594     p += make_mac_addr_device_path(p, ifr.ifr_ifru.ifru_hwaddr.sa_data, 0);
595     p += make_end_device_path       (p);
596     return(p);
597  out:
598     return NULL;
599 }
600
601 /**
602  * make_linux_load_option()
603  * @data - load option returned
604  *
605  * Returns 0 on error, length of load option created on success.
606  */
607 static unsigned long
608 make_linux_load_option(void *data)
609 {
610         EFI_LOAD_OPTION *load_option = data;
611         char *p = data, *q;
612         efi_char16_t description[64];
613         unsigned long datasize=0;
614
615         /* Write Attributes */
616         if (opts.active) load_option->attributes = LOAD_OPTION_ACTIVE;
617         else             load_option->attributes = 0;
618
619         p += sizeof(uint32_t);
620         /* skip writing file_path_list_length */
621         p += sizeof(uint16_t);
622         /* Write description.  This is the text that appears on the screen for the load option. */
623         memset(description, 0, sizeof(description));
624         efichar_from_char(description, opts.label, sizeof(description));
625         efichar_strncpy(load_option->description, description, sizeof(description));
626         p += efichar_strsize(load_option->description);
627
628         q = p;
629
630         if (opts.iface) {
631               p = (char *)make_net_load_option(p, opts.iface);
632         }
633         else {
634               p = (char *)make_disk_load_option(p, opts.iface);
635         }
636         if (p == NULL)
637                 return 0;
638
639         load_option->file_path_list_length = p - q;
640
641         datasize = (uint8_t *)p - (uint8_t *)data;
642         return datasize;
643 }
644
645 /*
646  * append_extra_args()
647  * appends all arguments from argv[] not snarfed by getopt
648  * as one long string onto data, up to maxchars.  allow for nulls
649  */
650
651 static unsigned long
652 append_extra_args_ascii(void *data, unsigned long maxchars)
653 {
654         char *p = data;
655         int i, appended=0;
656         unsigned long usedchars=0;
657         if (!data) return 0;
658
659
660         for (i=opts.optind; i < opts.argc && usedchars < maxchars; i++) {
661                 p = strncpy(p, opts.argv[i], maxchars-usedchars-1);
662                 p += strlen(p);
663                 appended=1;
664
665                 usedchars = p - (char *)data;
666
667                 /* Put a space between args */
668                 if (i < (opts.argc-1)) {
669
670                         p = strncpy(p, " ", maxchars-usedchars-1);
671                         p += strlen(p);
672                         usedchars = p - (char *)data;
673                 }
674
675         }
676         /* Remember the NULL */
677         if (appended) return strlen(data) + 1;
678         return 0;
679 }
680
681 static unsigned long
682 append_extra_args_unicode(void *data, unsigned long maxchars)
683 {
684         char *p = data;
685         int i, appended=0;
686         unsigned long usedchars=0;
687         if (!data) return 0;
688
689
690         for (i=opts.optind; i < opts.argc && usedchars < maxchars; i++) {
691                 p += efichar_from_char((efi_char16_t *)p, opts.argv[i],
692                                        maxchars-usedchars);
693                 usedchars = efichar_strsize(data) - sizeof(efi_char16_t);
694                 appended=1;
695
696                 /* Put a space between args */
697                 if (i < (opts.argc-1)) {
698                         p += efichar_from_char((efi_char16_t *)p, " ",
699                                                maxchars-usedchars);
700                         usedchars = efichar_strsize(data) -
701                                 sizeof(efi_char16_t);
702                 }
703         }
704
705         if (appended) return efichar_strsize( (efi_char16_t *)data );
706         return 0;
707 }
708
709 static unsigned long
710 append_extra_args_file(void *data, unsigned long maxchars)
711 {
712         char *p = data;
713         char *file = opts.extra_opts_file;
714         int fd = STDIN_FILENO;
715         ssize_t num_read=0;
716         unsigned long appended=0;
717
718         if (!data) return 0;
719
720         if (file && strncmp(file, "-", 1))
721                 fd = open(file, O_RDONLY);
722
723         if (fd == -1) {
724                 perror("Failed to open extra arguments file");
725                 exit(1);
726         }
727
728         do {
729                 num_read = read(fd, p, maxchars - appended);
730                 if (num_read < 0) {
731                         perror("Error reading extra arguments file");
732                         break;
733                 }
734                 else if (num_read>0) {
735                         appended += num_read;
736                         p += num_read;
737                 }
738         } while (num_read > 0 && ((maxchars - appended) > 0));
739
740         if (fd != STDIN_FILENO)
741                 close(fd);
742
743         return appended;
744 }
745
746
747 static unsigned long
748 append_extra_args(void *data, unsigned long maxchars)
749 {
750         unsigned long bytes_written=0;
751
752         if (opts.extra_opts_file)
753                 bytes_written += append_extra_args_file(data, maxchars);
754
755         if  (opts.unicode)
756                 bytes_written += append_extra_args_unicode(data, maxchars - bytes_written);
757         else
758                 bytes_written += append_extra_args_ascii(data, maxchars - bytes_written);
759         return bytes_written;
760 }
761
762
763
764 int
765 make_linux_efi_variable(efi_variable_t *var,
766                         unsigned int free_number)
767 {
768         efi_guid_t guid = EFI_GLOBAL_VARIABLE;
769         char buffer[16];
770         unsigned char *optional_data=NULL;
771         unsigned long load_option_size = 0, opt_data_size=0;
772
773         memset(buffer,    0, sizeof(buffer));
774
775         /* VariableName needs to be BootXXXX */
776         sprintf(buffer, "Boot%04X", free_number);
777
778         efichar_from_char(var->VariableName, buffer, 1024);
779
780         memcpy(&(var->VendorGuid), &guid, sizeof(guid));
781         var->Attributes =
782                 EFI_VARIABLE_NON_VOLATILE |
783                 EFI_VARIABLE_BOOTSERVICE_ACCESS |
784                 EFI_VARIABLE_RUNTIME_ACCESS;
785
786         /* Set Data[] and DataSize */
787
788         load_option_size =  make_linux_load_option(var->Data);
789
790         if (!load_option_size) return 0;
791
792         /* Set OptionalData (passed as binary to the called app) */
793         optional_data = var->Data + load_option_size;
794         opt_data_size = append_extra_args(optional_data,
795                                   sizeof(var->Data) - load_option_size);
796         var->DataSize = load_option_size + opt_data_size;
797         return var->DataSize;
798 }
799
800
801 int
802 variable_to_name(efi_variable_t *var, char *name)
803 {
804         char *p = name;
805         efichar_to_char(p, var->VariableName, PATH_MAX);
806         p += strlen(p);
807         p += sprintf(p, "-");
808         efi_guid_unparse(&var->VendorGuid, p);
809         return strlen(name);
810 }