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