More work on Intel AMT One Click Recovery support.
Ylian Saint-Hilaire committed
Mar 23, 2021 at 00:21 UTC
fd1248c3913428c0586741314ba688e9005bcb8d
1 file changed
+66
-7
amtmanager.js
+66
-7
@@ -825,7 +825,7 @@ module.exports.CreateAmtManager = function (parent) {
825
// Make sure the MPS server root certificate is present.
826
// Start by looking at existing certificates.
827
dev.ocrfile = file;
828
- dev.amtstack.BatchEnum(null, ['AMT_PublicKeyCertificate'], performOneClickRecoveryActionEx);
828
+ dev.amtstack.BatchEnum(null, ['AMT_PublicKeyCertificate', '*AMT_BootCapabilities'], performOneClickRecoveryActionEx);
829
}
830
}
831
}
@@ -834,9 +834,14 @@ module.exports.CreateAmtManager = function (parent) {
834
function performOneClickRecoveryActionEx(stack, name, responses, status) {
835
const dev = stack.dev;
836
if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
837
- if (status != 200) { dev.consoleMsg("Failed to get security information (" + status + ")."); removeAmtDevice(dev, 19); return; }
837
+ if (status != 200) { dev.consoleMsg("Failed to get security information (" + status + ")."); delete dev.ocrfile; return; }
838
+
839
+ // Check if this Intel AMT device supports OCR
840
+ if (responses['AMT_PublicKeyCertificate'].responses['ForceUEFIHTTPSBoot'] !== true) {
841
+ dev.consoleMsg("This Intel AMT device does not support UEFI HTTPS boot (" + status + ")."); delete dev.ocrfile; return;
842
+ }
843
839
- // Organize the certificates
844
+ // Organize the certificates and add the MPS root cert if missing
845
var xxCertificates = responses['AMT_PublicKeyCertificate'].responses;
846
for (var i in xxCertificates) {
847
xxCertificates[i].TrustedRootCertficate = (xxCertificates[i]['TrustedRootCertficate'] == true);
@@ -848,15 +853,63 @@ module.exports.CreateAmtManager = function (parent) {
853
attemptRootCertSync(dev, performOneClickRecoveryActionEx2, true);
854
}
855
856
+ // MPS root certificate was added
857
function performOneClickRecoveryActionEx2(dev) {
858
+ // Ask for Boot Settings Data
859
+ dev.amtstack.Get('AMT_BootSettingData', performOneClickRecoveryActionEx3, 0, 1);
860
+ }
861
+
862
+ // Getting Intel AMT Boot Settings Data
863
+ function performOneClickRecoveryActionEx3(stack, name, response, status) {
864
+ const dev = stack.dev;
865
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
866
+ if (status != 200) { dev.consoleMsg("Failed to get boot settings data (" + status + ")."); delete dev.ocrfile; return; }
867
+
868
// Generate the one-time URL.
853
- var cookie = obj.parent.encodeCookie({ a: 'ocr', f: dev.ocrfile }, obj.parent.loginCookieEncryptionKey)
854
- var url = 'https://' + parent.webserver.certificates.AmtMpsName + ':' + ((parent.args.mpsaliasport != null) ? parent.args.mpsaliasport : parent.args.mpsport) + '/ocr/' + cookie + '.iso';
869
+ //var cookie = obj.parent.encodeCookie({ a: 'ocr', f: dev.ocrfile }, obj.parent.loginCookieEncryptionKey)
870
+ //var url = 'https://' + parent.webserver.certificates.AmtMpsName + ':' + ((parent.args.mpsaliasport != null) ? parent.args.mpsaliasport : parent.args.mpsport) + '/ocr/' + cookie + '.iso';
871
+ delete dev.ocrfile;
872
+
873
+ // DEBUG
874
+ var url = 'https://' + parent.webserver.certificates.AmtMpsName + ':' + ((parent.args.mpsaliasport != null) ? parent.args.mpsaliasport : parent.args.mpsport) + '/ocr/abc.iso';
875
+ console.log('OCR: ' + url);
876
+
877
+ // Generate the boot data for OCR with URL
878
+ var r = response.Body;
879
+ r['UefiBootParametersArray'] = Buffer.from(makeUefiBootParam(1, url) + makeUefiBootParam(20, 1, 1) + makeUefiBootParam(30, 0, 2), 'binary').toString('base64');
880
+ r['UefiBootNumberOfParams'] = 3;
881
+ r['BootMediaIndex'] = 0; // Do not use boot media index for One Click Recovery (OCR)
882
+
883
+ // Set the boot order to null, this is needed for some Intel AMT versions that don't clear this automatically.
884
+ dev.amtstack.CIM_BootConfigSetting_ChangeBootOrder(null, function (stack, name, response, status) {
885
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
886
+ if (status != 200) { dev.consoleMsg("Failed to set boot order (" + status + ")."); return; }
887
+ dev.amtstack.Put('AMT_BootSettingData', r, performOneClickRecoveryActionEx4, 0, 1);
888
+ }, 0, 1);
889
+ }
890
856
- // TODO: Issue the WSMAN command.
857
- console.log('Perform One Click Recovery', url);
891
+ // Intel AMT Put Boot Settings
892
+ function performOneClickRecoveryActionEx4(stack, name, response, status) {
893
+ const dev = stack.dev;
894
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
895
+ if (status != 200) { dev.consoleMsg("Failed to set boot settings data (" + status + ")."); return; }
896
+ dev.amtstack.SetBootConfigRole(1, function (stack, name, response, status) {
897
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
898
+ if (status != 200) { dev.consoleMsg("Failed to set boot config role (" + status + ")."); return; }
899
+ var bootSource = 'Force OCR UEFI HTTPS Boot';
900
+ dev.amtstack.CIM_BootConfigSetting_ChangeBootOrder((bootSource == null) ? bootSource : '<Address xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://schemas.xmlsoap.org/ws/2004/08/addressing</Address><ReferenceParameters xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><ResourceURI xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_BootSourceSetting</ResourceURI><SelectorSet xmlns="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"><Selector Name="InstanceID">Intel(r) AMT: ' + bootSource + '</Selector></SelectorSet></ReferenceParameters>', function (stack, name, response, status) {
901
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
902
+ if (status != 200) { dev.consoleMsg("Failed to set boot config (" + status + ")."); return; }
903
+ dev.amtstack.RequestPowerStateChange(10, function (stack, name, response, status) { // 10 = Reset, 2 = Power Up
904
+ if (isAmtDeviceValid(dev) == false) return; // Device no longer exists, ignore this request.
905
+ if (status != 200) { dev.consoleMsg("Failed to perform power action (" + status + ")."); return; }
906
+ console.log('One Click Recovery Completed.');
907
+ });
908
+ });
909
+ }, 0, 1);
910
}
911
912
+
913
//
914
// Intel AMT Clock Syncronization
915
//
@@ -2255,6 +2308,12 @@ module.exports.CreateAmtManager = function (parent) {
2308
function getItem(x, y, z) { for (var i in x) { if (x[i][y] == z) return x[i]; } return null; }
2309
function IntToStr(v) { return String.fromCharCode((v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); }
2310
2311
+ // Returns a UEFI boot parameter in binary
2312
+ function makeUefiBootParam(type, data, len) {
2313
+ if (typeof data == 'number') { if (len == 1) { data = String.fromCharCode(data & 0xFF); } if (len == 2) { data = parent.common.ShortToStrX(data); } if (len == 4) { data = parent.common.IntToStrX(data); } }
2314
+ return parent.common.ShortToStrX(0x8086) + parent.common.ShortToStrX(type) + parent.common.IntToStrX(data.length) + data;
2315
+ }
2316
+
2317
function parseCertName(x) {
2318
var j, r = {}, xx = x.split(',');
2319
for (var i in xx) { j = xx[i].indexOf('='); r[xx[i].substring(0, j)] = xx[i].substring(j + 1); }