Created
November 3, 2025 16:25
-
-
Save sinuscosinustan/5e92ac16a57884fd621c45dd9806ea3a to your computer and use it in GitHub Desktop.
Multipart Upload Redfish endpoint logic from an Asus ASMB11-iKVM system (LuaJIT file)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| local var_0_0 = require("redfish-handler") | |
| local var_0_1 = require("redfish.multipart-handler") | |
| local var_0_2 = require("constants") | |
| local var_0_3 = require("config") | |
| local var_0_4 = require("utils") | |
| local var_0_5 = require("turbo") | |
| local var_0_6 = require("posix") | |
| local var_0_7 = require("underscore") | |
| local var_0_8 = require("turbo.log") | |
| local var_0_9 = require("update-service.update-service_config") | |
| local var_0_10 = require("update-service.update-service_utils") | |
| local var_0_11 = require("redfish.task-service") | |
| local var_0_12 = require("redfishinterface") | |
| local var_0_13 = class("MultipartPushHandler", var_0_1) | |
| local var_0_14 = { | |
| "multipart/form%-data;" | |
| } | |
| var_0_13:set_allowed_content_types(var_0_14) | |
| var_0_13.response = {} | |
| local var_0_15 = coroutine.yield | |
| local var_0_16 = "Redfish:UpdateService" | |
| local var_0_17 = "Redfish:UpdateService:ServiceEnabled" | |
| local var_0_18 = "Redfish:UpdateService:Oem:BMC:BIOSOOB" | |
| local var_0_19 = "/tmp/redfishfwupdate/" | |
| local var_0_20 = "/proc/ractrends/Helper/FwInfo2" | |
| function var_0_13.post(arg_1_0) | |
| print("we just called: MultipartPushHandler.post()") | |
| local var_1_0 = arg_1_0:get_request().connection.arguments | |
| local var_1_1 = "UpdateService.MultipartPush" | |
| local var_1_2 = false | |
| local var_1_3 = {} | |
| arg_1_0.response = {} | |
| if not var_0_10.is_service_enabled() then | |
| arg_1_0:error_service_disabled() | |
| end | |
| if var_0_4.event_task_service_status("Task") then | |
| local var_1_4 = arg_1_0:extract_request_data(var_1_0, var_1_3) | |
| if var_1_3.ImageType ~= "BIOSOOB" or var_1_3.BIOSOOBEnable ~= 0 then | |
| var_1_4 = var_1_4 and arg_1_0:save_imagefile(var_1_0, var_1_3) | |
| end | |
| if var_1_4 then | |
| local var_1_5 = var_0_11:new(arg_1_0.application, arg_1_0.request, "", arg_1_0.options) | |
| var_1_5:set_allowed_content_types(var_0_14) | |
| var_1_3.RequestAction = var_1_1 | |
| var_1_3.RequestPath = arg_1_0:get_request().path | |
| var_1_3.ClientAddr = arg_1_0:get_request().headers:get("X-Forwarded-For") or "127.0.0.1" | |
| var_1_3.Protocol = arg_1_0.request.protocol | |
| var_1_3.Url = arg_1_0.request.headers:get_url() | |
| var_1_3.Username = arg_1_0.username | |
| local var_1_6, var_1_7 = var_1_5:post_task({ | |
| action_key = "", | |
| op_type = "LUA_SCRIPT", | |
| ipc_data = "./update-service/update-service.lua", | |
| task_status = "OK", | |
| task_state = "New", | |
| wait_time = 1, | |
| task_name = "Update Service Task", | |
| web_request_data = var_1_3, | |
| messages = { | |
| arg_1_0:create_message("UpdateService", "PrepareUpdate", nil, { | |
| var_1_1 | |
| }) | |
| } | |
| }) | |
| local var_1_8 = var_0_3.SERVICE_PREFIX .. "/TaskService/Tasks/" .. var_1_7 | |
| arg_1_0:update_lastmodified(var_0_16, os.time()) | |
| arg_1_0.response.Messages = { | |
| arg_1_0:create_message("Task", "New", nil, { | |
| var_1_8 | |
| }), | |
| arg_1_0:create_message("UpdateService", "PrepareUpdate", nil, { | |
| var_1_1 or info | |
| }) | |
| } | |
| arg_1_0:set_header("Location", var_1_8) | |
| arg_1_0:set_scope("Redfish:" .. table.concat(arg_1_0:get_url_segments(), ":")) | |
| arg_1_0:set_context(var_0_2.UPDATE_SERVICE_CONTEXT) | |
| arg_1_0:set_type(var_0_2.UPDATE_SERVICE_TYPE) | |
| var_0_4.remove_nils(arg_1_0.response) | |
| arg_1_0:set_status(202) | |
| else | |
| arg_1_0:set_status(400) | |
| end | |
| else | |
| local var_1_9 = {} | |
| table.insert(var_1_9, arg_1_0:create_message("Ami", "SupportDisabled", { | |
| arg_1_0:get_request().path | |
| }, { | |
| "Task Service Daemon" | |
| })) | |
| arg_1_0:add_error_body(arg_1_0.response, 400, unpack(var_1_9)) | |
| end | |
| arg_1_0:set_response(arg_1_0.response) | |
| arg_1_0:output() | |
| end | |
| function var_0_13.extract_request_data(arg_2_0, arg_2_1, arg_2_2) | |
| local var_2_0 = false | |
| local var_2_1 = arg_2_0:parse_update_parameters(arg_2_1, arg_2_2) | |
| var_2_1 = arg_2_0:parse_oem_parameters(arg_2_1, arg_2_2) and var_2_1 | |
| var_2_1 = arg_2_0:parse_updateFile(arg_2_1) and var_2_1 | |
| var_2_1 = var_2_1 and arg_2_0:check_action_parameter(arg_2_2) | |
| if var_2_1 then | |
| arg_2_0:add_flashtype_and_uploadselector(arg_2_2) | |
| end | |
| return var_2_1 | |
| end | |
| function var_0_13.get_firmware_inventory_uri_map(arg_3_0) | |
| local var_3_0 = arg_3_0:get_db() | |
| local var_3_1 = var_0_15(var_3_0:keys(var_0_16 .. ":FirmwareInventory:*:Name")) | |
| local var_3_2 = var_3_0:pipeline() | |
| for iter_3_0, iter_3_1 in ipairs(var_3_1) do | |
| var_3_2:get(iter_3_1) | |
| end | |
| local var_3_3 = var_0_15(var_3_2:run()) | |
| local var_3_4 = {} | |
| for iter_3_2, iter_3_3 in ipairs(var_3_1) do | |
| var_3_4[iter_3_3:gsub(":Name$", ""):gsub("^Redfish:", var_0_3.SERVICE_PREFIX .. "/"):gsub(":", "/")] = var_3_3[iter_3_2] | |
| end | |
| return var_3_4 | |
| end | |
| function var_0_13.parse_update_parameters(arg_4_0, arg_4_1, arg_4_2) | |
| local var_4_0 = arg_4_0:parse_json_from_multipart_name(arg_4_1, "UpdateParameters") | |
| local var_4_1 = true | |
| if type(var_4_0) ~= "table" then | |
| return false | |
| end | |
| if var_4_0["@Redfish.OperationApplyTime"] ~= nil then | |
| arg_4_0:error_action_parameter_not_supported("@Redfish.OperationApplyTime", arg_4_0.response) | |
| var_4_1 = false | |
| end | |
| local var_4_2 = var_4_0.Targets or {} | |
| var_4_0.Targets = nil | |
| for iter_4_0, iter_4_1 in pairs(var_4_0) do | |
| arg_4_0:error_update_invalid_file_variable(iter_4_0, "UpdateParameters", arg_4_0.response) | |
| var_4_1 = false | |
| end | |
| local var_4_3 = arg_4_0:get_firmware_inventory_uri_map() | |
| local var_4_4 = {} | |
| for iter_4_2, iter_4_3 in ipairs(var_4_2) do | |
| local var_4_5 = var_4_3[iter_4_3:gsub("/*$", "")] | |
| if var_4_5 ~= nil then | |
| table.insert(var_4_4, var_4_5) | |
| else | |
| arg_4_0:check_allow_parameter_in_key("UpdateParameters", iter_4_3, "Targets", var_0_7.keys(var_4_3)) | |
| var_4_1 = false | |
| end | |
| end | |
| arg_4_2.Targets = var_4_4 | |
| arg_4_2.Targets_uri = var_4_2 | |
| return var_4_1 | |
| end | |
| function var_0_13.parse_oem_parameters(arg_5_0, arg_5_1, arg_5_2) | |
| local var_5_0 = arg_5_0:parse_json_from_multipart_name(arg_5_1, "OemParameters") | |
| local var_5_1 = true | |
| if type(var_5_0) ~= "table" then | |
| return false | |
| end | |
| local var_5_2 = { | |
| "BMC", | |
| "HPM" | |
| } | |
| if var_0_12.IsFeatureEnabled("CONFIG_SPX_FEATURE_BIOS_COMPONENT_SUPPORT") then | |
| var_5_2[#var_5_2 + 1] = "BIOS" | |
| var_5_2[#var_5_2 + 1] = "BIOSOOB" | |
| end | |
| if var_0_12.IsFeatureEnabled("CONFIG_SPX_FEATURE_INTEL_PFR_SUPPORT") then | |
| var_5_2[#var_5_2 + 1] = "PFR" | |
| end | |
| var_5_2[#var_5_2 + 1] = "PLDM" | |
| arg_5_0:check_allow_parameter_in_key("OemParameters", var_5_0.ImageType, "ImageType", var_5_2) | |
| arg_5_2.ImageType = var_5_0.ImageType | |
| var_5_0.ImageType = nil | |
| if arg_5_2.ImageType == "BIOSOOB" then | |
| if var_5_0.BIOSOOBEnable ~= nil then | |
| if var_5_0.BIOSOOBEnable == 0 or var_5_0.BIOSOOBEnable == 1 then | |
| arg_5_2.BIOSOOBEnable = var_5_0.BIOSOOBEnable | |
| print("Request_data.BIOSOOBEnable = " .. arg_5_2.BIOSOOBEnable) | |
| var_5_0.BIOSOOBEnable = nil | |
| else | |
| arg_5_0:error_action_parameter_format("BIOSOOBEnable", tostring(var_5_0.BIOSOOBEnable), arg_5_0.response) | |
| var_5_1 = false | |
| return var_5_1 | |
| end | |
| else | |
| arg_5_0:error_action_parameter_missing("BIOSOOBEnable", arg_5_0.response) | |
| var_5_1 = false | |
| return var_5_1 | |
| end | |
| end | |
| if arg_5_2.ImageType == "PFR" and var_0_12.IsFeatureEnabled("CONFIG_SPX_FEATURE_INTEL_PFR_SUPPORT") then | |
| arg_5_2.defer = var_5_0.defer | |
| var_5_0.defer = nil | |
| arg_5_2.active = var_5_0.active | |
| var_5_0.active = nil | |
| arg_5_2.recovery = var_5_0.recovery | |
| var_5_0.recovery = nil | |
| arg_5_2.preserveconf = var_5_0.preserveconf | |
| var_5_0.preserveconf = nil | |
| end | |
| if var_5_0.SaveBIOSSettings ~= nil then | |
| if var_5_0.SaveBIOSSettings == 0 or var_5_0.SaveBIOSSettings == 1 then | |
| arg_5_2.SaveBIOSSettings = var_5_0.SaveBIOSSettings | |
| else | |
| arg_5_2.SaveBIOSSettings = 0 | |
| end | |
| else | |
| print("request_data.SaveBIOSSettings is nil") | |
| arg_5_2.SaveBIOSSettings = 0 | |
| end | |
| var_5_0.SaveBIOSSettings = nil | |
| arg_5_2.Platform = var_5_0.Platform | |
| var_5_0.Platform = nil | |
| if arg_5_2.Platform ~= nil then | |
| local var_5_3 = arg_5_0:get_db() | |
| local var_5_4 = var_0_15(var_5_3:smembers("Redfish:UpdateService:OemParameters:Platform")) | |
| if not var_0_4.array_has(var_5_4, arg_5_2.Platform) then | |
| arg_5_0:check_allow_parameter_in_key("OemParameters", arg_5_2.Platform, "Platform", var_5_4, arg_5_0.response) | |
| var_5_1 = false | |
| end | |
| end | |
| for iter_5_0, iter_5_1 in pairs(var_5_0) do | |
| arg_5_0:error_action_parameter_unknown(iter_5_0, arg_5_0.response) | |
| var_5_1 = false | |
| end | |
| return var_5_1 | |
| end | |
| function var_0_13.parse_updateFile(arg_6_0, arg_6_1) | |
| local var_6_0 = true | |
| local var_6_1 = "UpdateFile" | |
| local var_6_2 = arg_6_1[var_6_1] | |
| if var_6_2 ~= nil then | |
| if var_6_2[1][1] == "" then | |
| arg_6_0:error_update_required_key_parameter_missing(var_6_1, arg_6_0.response) | |
| return false | |
| end | |
| else | |
| arg_6_0:error_update_required_key_parameter_missing(var_6_1, arg_6_0.response) | |
| return false | |
| end | |
| return var_6_0 | |
| end | |
| function var_0_13.parse_json_from_multipart_name(arg_7_0, arg_7_1, arg_7_2) | |
| local var_7_0 | |
| local var_7_1 = arg_7_1[arg_7_2] | |
| local var_7_2 | |
| if var_7_1 ~= nil then | |
| local var_7_3 = var_7_1[1]["content-type"] | |
| local var_7_4 = var_7_1[1][1] | |
| if var_7_3 ~= nil and string.find(var_7_3, "application/json") then | |
| local var_7_5, var_7_6 = pcall(var_0_5.escape.json_decode, var_7_4) | |
| var_7_0 = var_7_6 | |
| if var_7_5 == false then | |
| arg_7_0:error_update_malformed_json_file(arg_7_2) | |
| elseif var_7_0 == nil then | |
| arg_7_0:error_action_parameter_format(arg_7_2, tostring(var_7_4), arg_7_0.response) | |
| end | |
| elseif var_7_1[1][1] == "" then | |
| arg_7_0:error_update_required_key_parameter_missing(arg_7_2, arg_7_0.response) | |
| else | |
| arg_7_0:error_update_invalid_extension_type(arg_7_2, tostring(var_7_3), arg_7_0.response) | |
| end | |
| else | |
| arg_7_0:error_update_required_key_parameter_missing(arg_7_2, arg_7_0.response) | |
| end | |
| return var_7_0 | |
| end | |
| function var_0_13.add_flashtype_and_uploadselector(arg_8_0, arg_8_1) | |
| local var_8_0 | |
| local var_8_1 | |
| for iter_8_0, iter_8_1 in ipairs(arg_8_1.Targets) do | |
| if iter_8_1:match("Image1$") then | |
| var_8_0 = true | |
| end | |
| if iter_8_1:match("Image2$") then | |
| var_8_1 = true | |
| end | |
| end | |
| if not var_8_0 and not var_8_1 then | |
| if var_0_6.stat(var_0_20) then | |
| arg_8_1.FlashType = "DUALIMAGEFwUpdate" | |
| arg_8_1.UploadSelector = "AutoInactive" | |
| else | |
| arg_8_1.FlashType = "FULLFwUpdate" | |
| arg_8_1.UploadSelector = "Default" | |
| end | |
| elseif var_8_0 and var_8_1 then | |
| arg_8_1.UploadSelector = "ImageBoth" | |
| arg_8_1.FlashType = "DUALIMAGEFwUpdate" | |
| elseif var_8_0 then | |
| arg_8_1.UploadSelector = "Image1" | |
| arg_8_1.FlashType = "DUALIMAGEFwUpdate" | |
| else | |
| arg_8_1.UploadSelector = "Image2" | |
| arg_8_1.FlashType = "DUALIMAGEFwUpdate" | |
| end | |
| end | |
| function var_0_13.check_action_parameter(arg_9_0, arg_9_1) | |
| local var_9_0 = true | |
| if arg_9_1.ImageType == "BIOS" or arg_9_1.ImageType == "BIOSOOB" then | |
| for iter_9_0, iter_9_1 in ipairs(arg_9_1.Targets) do | |
| if iter_9_1 ~= "BIOS" then | |
| arg_9_0:error_action_parameter_format("Targets", arg_9_1.Targets_uri[iter_9_0], arg_9_0.response) | |
| var_9_0 = false | |
| end | |
| end | |
| end | |
| if arg_9_1.ImageType == "BMC" then | |
| for iter_9_2, iter_9_3 in ipairs(arg_9_1.Targets) do | |
| if not iter_9_3:find("BMC", 1, true) then | |
| arg_9_0:error_action_parameter_format("Targets", arg_9_1.Targets_uri[iter_9_2], arg_9_0.response) | |
| var_9_0 = false | |
| end | |
| end | |
| end | |
| if arg_9_1.ImageType == "PFR" then | |
| params = { | |
| "defer", | |
| "active", | |
| "recovery", | |
| "preserveconf" | |
| } | |
| for iter_9_4, iter_9_5 in ipairs(params) do | |
| local var_9_1 = arg_9_1[iter_9_5] | |
| if var_9_1 == nil then | |
| arg_9_1[iter_9_5] = false | |
| elseif type(var_9_1) ~= "boolean" then | |
| arg_9_0:error_action_parameter_format(iter_9_5, var_9_1, arg_9_0.response) | |
| var_9_0 = false | |
| end | |
| print("PFR paraname", iter_9_5, arg_9_1[iter_9_5]) | |
| end | |
| end | |
| return var_9_0 | |
| end | |
| function var_0_13.check_allow_parameter_in_key(arg_10_0, arg_10_1, arg_10_2, arg_10_3, arg_10_4, arg_10_5) | |
| if arg_10_2 == nil or type(arg_10_2) ~= "string" then | |
| arg_10_0:error_update_required_value_parameters_missing(arg_10_1, tostring(arg_10_3), arg_10_5) | |
| elseif not var_0_5.util.is_in(arg_10_2, arg_10_4) then | |
| arg_10_0:error_update_invalid_variable_value(arg_10_2, tostring(arg_10_3), arg_10_1, arg_10_5) | |
| end | |
| end | |
| local function var_0_21() | |
| for iter_11_0 in var_0_6.files(var_0_19) or {} do | |
| if string.match(iter_11_0, "(.-%.hpm)") or string.match(iter_11_0, "(.-%.bin)") or string.match(iter_11_0, "(.-%.ima)") then | |
| os.remove(string.format("%s/%s", var_0_19, iter_11_0)) | |
| end | |
| end | |
| end | |
| local function var_0_22(arg_12_0, arg_12_1) | |
| local var_12_0 = arg_12_1.ImageType | |
| return ({ | |
| BIOSOOB = "oob.cap", | |
| HPM = "rom.hpm", | |
| PFR = "pfr.bin", | |
| PLDM = "pldm.bin", | |
| BIOS = "bios.bin", | |
| BMC = "rom.ima" | |
| })[var_12_0] | |
| end | |
| local function var_0_23(arg_13_0, arg_13_1) | |
| local var_13_0 = arg_13_1.ImageType | |
| local var_13_1 = { | |
| BMC = var_0_12.is_bmc_image_valid, | |
| HPM = var_0_12.is_hpm_image_valid, | |
| BIOS = var_0_12.is_bios_image_valid, | |
| PFR = var_0_12.is_pfr_update_capsule_valid | |
| } | |
| local var_13_2 = true | |
| if var_13_1[var_13_0] then | |
| var_13_2 = var_13_1[var_13_0](arg_13_0) | |
| end | |
| return var_13_2 | |
| end | |
| function var_0_13.save_imagefile(arg_14_0, arg_14_1, arg_14_2) | |
| local var_14_0 = false | |
| local var_14_1 = "UpdateFile" | |
| local var_14_2 = arg_14_1[var_14_1] | |
| if var_14_2 ~= nil then | |
| local var_14_3 = var_14_2[1]["content-disposition"].filename | |
| local var_14_4 = var_14_2[1][1] | |
| local var_14_5 = var_14_2[1].filepath | |
| if var_14_3 ~= nil then | |
| local var_14_6 = var_0_22(var_14_3, arg_14_2) | |
| if var_14_6 then | |
| local var_14_7 | |
| if arg_14_2.ImageType == "BIOSOOB" then | |
| var_14_7 = string.format("/tmp/%s", var_14_6) | |
| else | |
| var_14_7 = string.format("%s/%s", var_0_19, var_14_6) | |
| end | |
| arg_14_2.image_path = var_14_7 | |
| var_0_21() | |
| var_0_10.remove_cached_files() | |
| if var_14_5 then | |
| os.rename(var_14_5, var_14_7) | |
| else | |
| var_0_10.chunked_write(var_14_4, var_14_7) | |
| local var_14_8 | |
| var_14_2[1][1] = nil | |
| arg_14_1[var_14_1] = nil | |
| end | |
| collectgarbage() | |
| collectgarbage() | |
| var_14_0 = var_0_23(var_14_7, arg_14_2) | |
| if not var_14_0 then | |
| os.remove(var_14_7) | |
| arg_14_0:add_error_body(arg_14_0.response, 400, arg_14_0:create_message("UpdateService", "InvalidFirmwareImageFormat", nil, tostring(var_14_3))) | |
| end | |
| else | |
| arg_14_0:add_error_body(arg_14_0.response, 400, arg_14_0:create_message("AmiOem.1.0.0", "InvalidFirmwareImageFormat", nil, tostring(var_14_3))) | |
| end | |
| else | |
| arg_14_0:error_action_parameter_type(var_14_1, tostring(var_14_3), arg_14_0.response) | |
| end | |
| else | |
| arg_14_0:error_update_required_key_parameter_missing(var_14_1, arg_14_0.response) | |
| end | |
| return var_14_0 | |
| end | |
| return var_0_13 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment