Skip to content

Instantly share code, notes, and snippets.

@sinuscosinustan
Created November 3, 2025 16:25
Show Gist options
  • Select an option

  • Save sinuscosinustan/5e92ac16a57884fd621c45dd9806ea3a to your computer and use it in GitHub Desktop.

Select an option

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)
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