diff --git a/providers/redfish/firmware.go b/providers/redfish/firmware.go
index 94112521..92b6528f 100644
--- a/providers/redfish/firmware.go
+++ b/providers/redfish/firmware.go
@@ -106,7 +106,23 @@ func (c *Conn) FirmwareInstall(ctx context.Context, component, applyAt string, f
 		"UpdateFile":       reader,
 	}
 
-	resp, err := c.runRequestWithMultipartPayload(http.MethodPost, "/redfish/v1/UpdateService/MultipartUpload", payload)
+	updateService, err := c.redfishwrapper.UpdateService()
+
+	if err != nil {
+		return "", errors.Wrap(bmclibErrs.ErrFirmwareUpload, err.Error())
+	}
+
+	var resp *http.Response
+	if updateService.MultipartHTTPPushURI != "" {
+		// TODO: should use updateService.MultipartHTTPPushURI rather than hardcoded path
+		// but should be tested when modified
+		resp, err = c.runRequestWithMultipartPayload(http.MethodPost, "/redfish/v1/UpdateService/MultipartUpload", payload)
+	} else if updateService.HTTPPushURI != "" {
+		resp, err = c.runRequestWithPayload(http.MethodPost, updateService.HTTPPushURI, payload["UpdateFile"])
+	} else {
+		return "", errors.Wrap(bmclibErrs.ErrFirmwareUpload, "No URI available for push updates")
+	}
+
 	if err != nil {
 		return "", errors.Wrap(bmclibErrs.ErrFirmwareUpload, err.Error())
 	}
@@ -118,10 +134,21 @@ func (c *Conn) FirmwareInstall(ctx context.Context, component, applyAt string, f
 		)
 	}
 
-	// The response contains a location header pointing to the task URI
-	// Location: /redfish/v1/TaskService/Tasks/JID_467696020275
-	if strings.Contains(resp.Header.Get("Location"), "JID_") {
-		taskID = strings.Split(resp.Header.Get("Location"), "JID_")[1]
+	return location2TaskID(resp.Header.Get("Location"))
+}
+
+func location2TaskID(location string) (taskID string, err error) {
+	if strings.Contains(location, "JID_") {
+		// The response contains a location header pointing to the task URI
+		// Location: /redfish/v1/TaskService/Tasks/JID_467696020275
+		taskID = strings.Split(location, "JID_")[1]
+	} else if strings.Contains(location, "/Monitor") {
+		// OpenBMC returns a monitor URL in Location
+		// Location: /redfish/v1/TaskService/Tasks/12/Monitor
+		splits := strings.Split(location, "/")
+		taskID = splits[5]
+	} else {
+		return "", bmclibErrs.ErrTaskNotFound
 	}
 
 	return taskID, nil
@@ -134,10 +161,41 @@ func (c *Conn) FirmwareInstallStatus(ctx context.Context, installVersion, compon
 		return state, errors.Wrap(err, "unable to determine device vendor, model attributes")
 	}
 
+	// component is not used, we hack it for tests
+	if component == "testOpenbmc" {
+		vendor = constants.Packet
+	}
+
 	var task *gofishrf.Task
 	switch {
 	case strings.Contains(vendor, constants.Dell):
 		task, err = c.dellJobAsRedfishTask(taskID)
+		if task == nil {
+			return state, errors.New("failed to lookup task status for task ID: " + taskID)
+		}
+
+		state = strings.ToLower(string(task.TaskState))
+
+	case strings.Contains(vendor, constants.Packet):
+		resp, _ := c.redfishwrapper.Get("/redfish/v1/TaskService/Tasks/" + taskID)
+		if resp.StatusCode != 200 {
+			err = errors.Wrap(
+				bmclibErrs.ErrFirmwareInstall,
+				"HTTP Error: "+fmt.Sprint(resp.StatusCode),
+			)
+
+			state = "failed"
+			break
+		}
+
+		//task, err := gofishrf.GetTask(c.redfishwrapper, "/redfish/v1/TaskService/Tasks/" + taskID)
+		//fmt.Printf("task:", task);
+
+		data, _ := io.ReadAll(resp.Body)
+		resp.Body.Close()
+
+		state, err = c.openbmcGetStatus(data)
+
 	default:
 		err = errors.Wrap(
 			bmclibErrs.ErrNotImplemented,
@@ -149,12 +207,6 @@ func (c *Conn) FirmwareInstallStatus(ctx context.Context, installVersion, compon
 		return state, err
 	}
 
-	if task == nil {
-		return state, errors.New("failed to lookup task status for task ID: " + taskID)
-	}
-
-	state = strings.ToLower(string(task.TaskState))
-
 	// so much for standards...
 	switch state {
 	case "starting", "downloading", "downloaded":
@@ -189,9 +241,10 @@ func (c *Conn) firmwareUpdateCompatible(ctx context.Context) (err error) {
 		return errors.Wrap(bmclibErrs.ErrRedfishUpdateService, "service disabled")
 	}
 
-	// for now we expect multipart HTTP push update support
-	if updateService.MultipartHTTPPushURI == "" {
-		return errors.Wrap(bmclibErrs.ErrRedfishUpdateService, "Multipart HTTP push updates not supported")
+	// for now we expect multipart HTTP push update support,
+	// or at least the unstructured HTTP push update support
+	if updateService.MultipartHTTPPushURI == "" && updateService.HTTPPushURI == "" {
+		return errors.Wrap(bmclibErrs.ErrRedfishUpdateService, "No HTTP push updates supported (multipart or unstructured)")
 	}
 
 	return nil
@@ -248,6 +301,17 @@ func (c *Conn) runRequestWithMultipartPayload(method, url string, payload map[st
 	return c.redfishwrapper.RunRawRequestWithHeaders(method, url, bytes.NewReader(payloadBuffer.Bytes()), payloadWriter.FormDataContentType(), nil)
 }
 
+// Updates using an unstrctured HTTP updates
+func (c *Conn) runRequestWithPayload(method, url string, payload io.Reader) (*http.Response, error) {
+	if url == "" {
+		return nil, fmt.Errorf("unable to execute request, no target provided")
+	}
+
+	b, _ := io.ReadAll(payload)
+	payloadReadSeeker := bytes.NewReader(b)
+	return c.redfishwrapper.RunRawRequestWithHeaders(method, url, payloadReadSeeker, "application/octet-stream", nil)
+}
+
 // sets up the UpdateParameters MIMEHeader for the multipart form
 // the Go multipart writer CreateFormField does not currently let us set Content-Type on a MIME Header
 // https://cs.opensource.google/go/go/+/refs/tags/go1.17.8:src/mime/multipart/writer.go;l=151
@@ -276,6 +340,8 @@ func (c *Conn) GetFirmwareInstallTaskQueued(ctx context.Context, component strin
 	switch {
 	case strings.Contains(vendor, constants.Dell):
 		task, err = c.getDellFirmwareInstallTaskScheduled(component)
+	case strings.Contains(vendor, constants.Packet):
+		//task, err = c.getDellFirmwareInstallTaskScheduled(component)
 	default:
 		err = errors.Wrap(
 			bmclibErrs.ErrNotImplemented,
diff --git a/providers/redfish/firmware_test.go b/providers/redfish/firmware_test.go
index 8e098e4d..ea8bdcde 100644
--- a/providers/redfish/firmware_test.go
+++ b/providers/redfish/firmware_test.go
@@ -19,7 +19,7 @@ import (
 	"github.com/bmc-toolbox/common"
 )
 
-// handler registered in mock_test.go
+// handler registered in main_test.go
 func multipartUpload(w http.ResponseWriter, r *http.Request) {
 	if r.Method != "POST" {
 		w.WriteHeader(http.StatusNotFound)
@@ -157,3 +157,47 @@ func Test_firmwareUpdateCompatible(t *testing.T) {
 		t.Fatal(err)
 	}
 }
+
+func Test_runRequestWithPayload(t *testing.T) {
+	var reader io.Reader
+	resp, err := mockClient.runRequestWithPayload(http.MethodPost, "", reader)
+	if resp != nil {
+		t.Fatal(err)
+	}
+}
+
+// referenced in main_test.go
+func openbmcStatus(w http.ResponseWriter, r *http.Request) {
+	mytask := `{
+  "@odata.id": "/redfish/v1/TaskService/Tasks/15",
+  "@odata.type": "#Task.v1_4_3.Task",
+  "Id": "15",
+  "Messages": [
+    {
+      "@odata.type": "#Message.v1_1_1.Message",
+      "Message": "The task with Id '15' has started.",
+      "MessageArgs": [
+        "15"
+      ],
+      "MessageId": "TaskEvent.1.0.3.TaskStarted",
+      "MessageSeverity": "OK",
+      "Resolution": "None."
+    }
+  ],
+  "Name": "Task 15",
+  "TaskState": "TestState",
+  "TaskStatus": "TestStatus"
+}
+`
+	_, _ = w.Write([]byte(mytask))
+}
+
+func Test_FirmwareInstall2(t *testing.T) {
+	state, err := mockClient.FirmwareInstallStatus(context.TODO(), "", "testOpenbmc", "15")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if state != "unknown: teststate" {
+		t.Fatal("Wrong test state:", state)
+	}
+}
diff --git a/providers/redfish/main_test.go b/providers/redfish/main_test.go
index 924dfe8a..d68dc399 100644
--- a/providers/redfish/main_test.go
+++ b/providers/redfish/main_test.go
@@ -59,6 +59,7 @@ func TestMain(m *testing.M) {
 		handler.HandleFunc("/redfish/v1/SessionService/Sessions", sessionService)
 		handler.HandleFunc("/redfish/v1/UpdateService/MultipartUpload", multipartUpload)
 		handler.HandleFunc("/redfish/v1/Managers/iDRAC.Embedded.1/Oem/Dell/Jobs?$expand=*($levels=1)", dellJobs)
+		handler.HandleFunc("/redfish/v1/TaskService/Tasks/15", openbmcStatus)
 
 		return httptest.NewTLSServer(handler)
 	}()
diff --git a/providers/redfish/tasks.go b/providers/redfish/tasks.go
index bc6aaeb1..668de8f1 100644
--- a/providers/redfish/tasks.go
+++ b/providers/redfish/tasks.go
@@ -2,6 +2,7 @@ package redfish
 
 import (
 	"encoding/json"
+	"fmt"
 	"io"
 	"strconv"
 	"strings"
@@ -171,3 +172,32 @@ func (c *Conn) dellJobs(state string) ([]*gofishrf.Task, error) {
 
 	return tasks, nil
 }
+
+func (c *Conn) openbmcGetStatus(jsonstr []byte) (state string, err error) {
+	type TaskMsg struct {
+		Message string
+	}
+
+	type TaskStatus struct {
+		TaskState  string
+		TaskStatus string
+		Messages   []TaskMsg
+	}
+
+	var status TaskStatus
+
+	err = json.Unmarshal(jsonstr, &status)
+	if err != nil {
+		fmt.Println(err)
+	} else {
+		state = strings.ToLower(status.TaskState)
+		if state != "running" {
+			// Display all messages when not running (failed or completed)
+			fmt.Println(status.TaskState, status.TaskStatus)
+			for _, m := range status.Messages {
+				fmt.Println(m.Message)
+			}
+		}
+	}
+	return state, err
+}
diff --git a/providers/redfish/tasks_test.go b/providers/redfish/tasks_test.go
index bf1a376b..830fbaca 100644
--- a/providers/redfish/tasks_test.go
+++ b/providers/redfish/tasks_test.go
@@ -38,3 +38,31 @@ func Test_dellPurgeScheduledFirmwareInstallJob(t *testing.T) {
 		t.Fatal(err)
 	}
 }
+
+func Test_openbmcGetStatus(t *testing.T) {
+	var err error
+	var state string
+
+	// empty (invalid json)
+	_, err = mockClient.openbmcGetStatus([]byte(""))
+	if err == nil {
+		t.Fatal("no error with empty invalid json")
+	}
+
+	// empty valid json
+	_, err = mockClient.openbmcGetStatus([]byte("{}"))
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// empty valid json
+	state, err = mockClient.openbmcGetStatus([]byte(
+		"{\"Id\":\"15\", \"TaskState\": \"TestState\", \"TaskStatus\": \"TestStatus\"}",
+	))
+	if err != nil {
+		t.Fatal(err)
+	}
+	if state != "teststate" {
+		t.Fatal("Wrong test state:", state)
+	}
+}