c/agent: include EFI support in hardware report

Adds firmware EFI support status to the hardware report.
It is represented as an enum which is populated based on two different
data sources. The ENABLED state is set if Linux has EFI runtime
services available. The SUPPORTED/UNSUPPORTED states depend on the
SMBIOS tables provided by the firmware
and are used if EFI runtime services are not available.
If neither are available, UNKNOWN is used.

Change-Id: I7642ccda14d5494294a7463755de18e73a8a9c53
Reviewed-on: https://review.monogon.dev/c/monogon/+/1571
Reviewed-by: Serge Bazanski <serge@monogon.tech>
Tested-by: Jenkins CI
diff --git a/cloud/agent/hwreport.go b/cloud/agent/hwreport.go
index 3b82d27..c92244d 100644
--- a/cloud/agent/hwreport.go
+++ b/cloud/agent/hwreport.go
@@ -45,6 +45,14 @@
 		c.node.Product = smbTbl.SystemInformationRaw.ProductName
 		c.node.SerialNumber = smbTbl.SystemInformationRaw.SerialNumber
 	}
+	if smbTbl.BIOSInformationRaw != nil && smbTbl.BIOSInformationRaw.StructureVersion.AtLeast(2, 2) {
+		uefiSupport := smbTbl.BIOSInformationRaw.BIOSCharacteristicsExtensionByte2&smbios.UEFISpecificationSupported != 0
+		if uefiSupport {
+			c.node.EfiSupport = api.EFISupport_EFI_SUPPORTED
+		} else {
+			c.node.EfiSupport = api.EFISupport_EFI_UNSUPPORTED
+		}
+	}
 	for _, d := range smbTbl.MemoryDevicesRaw {
 		if d.StructureVersion.AtLeast(3, 2) && d.MemoryTechnology != 0x03 {
 			// If MemoryTechnology is available, only count DRAM
@@ -400,6 +408,7 @@
 	hwReportCtx := hwReportContext{
 		node: &api.Node{},
 	}
+	hwReportCtx.node.EfiSupport = api.EFISupport_EFI_UNKNOWN
 
 	hwReportCtx.gatherCPU()
 	hwReportCtx.gatherSMBIOS()
@@ -415,5 +424,9 @@
 	hwReportCtx.gatherNICs()
 	hwReportCtx.gatherBlockDevices()
 
+	if _, err := os.Stat("/sys/firmware/efi/runtime"); err == nil {
+		hwReportCtx.node.EfiSupport = api.EFISupport_EFI_ENABLED
+	}
+
 	return hwReportCtx.node, hwReportCtx.errors
 }