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