m/p/efivarfs: refactor

This accomplishes three things:

First, split out the variable access layer from the rest of the code.
This cleans up the attribute handling, which is now done centrally as
well as making the high-level functions very short and clean. They now
also return better errors.

Second this introduces proper types for LoadOption, which can now also
be unmarshaled which was a requirement for A/B updates. This required
implementation of EFI's DevicePath structure.
While refactoring the higher-level functions for this, this also
fixes a bug where the variable index (the 4 hex nibbles at the end) were
improperly generated as lowercase hex.

Third, this adds new high-level functions for interacting with more
boot-related variables needed for the A/B effort.

Change-Id: I53490fa4898a5e7a5498ecc05a9078bd2d66c26e
Reviewed-on: https://review.monogon.dev/c/monogon/+/1855
Tested-by: Jenkins CI
Reviewed-by: Serge Bazanski <serge@monogon.tech>
diff --git a/cloud/agent/install.go b/cloud/agent/install.go
index e05a57c..656f258 100644
--- a/cloud/agent/install.go
+++ b/cloud/agent/install.go
@@ -120,7 +120,7 @@
 	if err != nil {
 		return err
 	}
-	bootEntryIdx, err := efivarfs.CreateBootEntry(be)
+	bootEntryIdx, err := efivarfs.AddBootEntry(be)
 	if err != nil {
 		return fmt.Errorf("error creating EFI boot entry: %w", err)
 	}