diff --git a/ironic/drivers/modules/redfish/firmware_utils.py b/ironic/drivers/modules/redfish/firmware_utils.py
new file mode 100644
index 0000000000..35e4bb1f29
--- /dev/null
+++ b/ironic/drivers/modules/redfish/firmware_utils.py
@@ -0,0 +1,58 @@
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import jsonschema
+from oslo_log import log
+
+from ironic.common import exception
+from ironic.common.i18n import _
+
+LOG = log.getLogger(__name__)
+
+_UPDATE_FIRMWARE_SCHEMA = {
+    "$schema": "http://json-schema.org/schema#",
+    "title": "update_firmware clean step schema",
+    "type": "array",
+    # list of firmware update images
+    "items": {
+        "type": "object",
+        "required": ["url"],
+        "properties": {
+            "url": {
+                "description": "URL for firmware file",
+                "type": "string",
+                "minLength": 1
+            },
+            "wait": {
+                "description": "optional wait time for firmware update",
+                "type": "integer",
+                "minimum": 1
+            }
+        },
+        "additionalProperties": False
+    }
+}
+
+
+def validate_update_firmware_args(firmware_images):
+    """Validate ``update_firmware`` step input argument
+
+    :param firmware_images: args to validate.
+    :raises: InvalidParameterValue When argument is not valid
+    """
+    try:
+        jsonschema.validate(firmware_images, _UPDATE_FIRMWARE_SCHEMA)
+    except jsonschema.ValidationError as err:
+        raise exception.InvalidParameterValue(
+            _('Invalid firmware update %(firmware_images)s. Errors: %(err)s')
+            % {'firmware_images': firmware_images, 'err': err})
diff --git a/ironic/drivers/modules/redfish/management.py b/ironic/drivers/modules/redfish/management.py
index 790f46eaa1..cb56a821b3 100644
--- a/ironic/drivers/modules/redfish/management.py
+++ b/ironic/drivers/modules/redfish/management.py
@@ -35,6 +35,7 @@ from ironic.conf import CONF
 from ironic.drivers import base
 from ironic.drivers.modules import boot_mode_utils
 from ironic.drivers.modules import deploy_utils
+from ironic.drivers.modules.redfish import firmware_utils
 from ironic.drivers.modules.redfish import utils as redfish_utils
 
 LOG = log.getLogger(__name__)
@@ -759,6 +760,7 @@ class RedfishManagement(base.ManagementInterface):
         :returns: None if it is completed.
         :raises: RedfishError on an error from the Sushy library.
         """
+        firmware_utils.validate_update_firmware_args(firmware_images)
         node = task.node
 
         LOG.debug('Updating firmware on node %(node_uuid)s with firmware '
diff --git a/ironic/tests/unit/drivers/modules/redfish/test_firmware_utils.py b/ironic/tests/unit/drivers/modules/redfish/test_firmware_utils.py
new file mode 100644
index 0000000000..60c66c0249
--- /dev/null
+++ b/ironic/tests/unit/drivers/modules/redfish/test_firmware_utils.py
@@ -0,0 +1,88 @@
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from ironic.common import exception
+from ironic.drivers.modules.redfish import firmware_utils
+from ironic.tests import base
+
+
+class FirmwareUtilsTestCase(base.TestCase):
+
+    def test_validate_update_firmware_args(self):
+        firmware_images = [
+            {
+                "url": "http://192.0.2.10/BMC_4_22_00_00.EXE",
+                "wait": 300
+            },
+            {
+                "url": "https://192.0.2.10/NIC_19.0.12_A00.EXE"
+            }
+        ]
+        firmware_utils.validate_update_firmware_args(firmware_images)
+
+    def test_validate_update_firmware_args_not_list(self):
+        firmware_images = {
+            "url": "http://192.0.2.10/BMC_4_22_00_00.EXE",
+            "wait": 300
+        }
+        self.assertRaisesRegex(
+            exception.InvalidParameterValue, "is not of type 'array'",
+            firmware_utils.validate_update_firmware_args, firmware_images)
+
+    def test_validate_update_firmware_args_unknown_key(self):
+        firmware_images = [
+            {
+                "url": "http://192.0.2.10/BMC_4_22_00_00.EXE",
+                "wait": 300,
+            },
+            {
+                "url": "https://192.0.2.10/NIC_19.0.12_A00.EXE",
+                "something": "unknown"
+            }
+        ]
+        self.assertRaisesRegex(
+            exception.InvalidParameterValue, "'something' was unexpected",
+            firmware_utils.validate_update_firmware_args, firmware_images)
+
+    def test_validate_update_firmware_args_url_missing(self):
+        firmware_images = [
+            {
+                "url": "http://192.0.2.10/BMC_4_22_00_00.EXE",
+                "wait": 300,
+            },
+            {
+                "wait": 300
+            }
+        ]
+        self.assertRaisesRegex(
+            exception.InvalidParameterValue,
+            "'url' is a required property",
+            firmware_utils.validate_update_firmware_args, firmware_images)
+
+    def test_validate_update_firmware_args_url_not_string(self):
+        firmware_images = [{
+            "url": 123,
+            "wait": 300
+        }]
+        self.assertRaisesRegex(
+            exception.InvalidParameterValue, "123 is not of type 'string'",
+            firmware_utils.validate_update_firmware_args, firmware_images)
+
+    def test_validate_update_firmware_args_wait_not_int(self):
+        firmware_images = [{
+            "url": "http://192.0.2.10/BMC_4_22_00_00.EXE",
+            "wait": 'abc'
+        }]
+        self.assertRaisesRegex(
+            exception.InvalidParameterValue, "'abc' is not of type 'integer'",
+            firmware_utils.validate_update_firmware_args, firmware_images)
diff --git a/ironic/tests/unit/drivers/modules/redfish/test_management.py b/ironic/tests/unit/drivers/modules/redfish/test_management.py
index 5930816ab8..b467006648 100644
--- a/ironic/tests/unit/drivers/modules/redfish/test_management.py
+++ b/ironic/tests/unit/drivers/modules/redfish/test_management.py
@@ -856,6 +856,14 @@ class RedfishManagementTestCase(db_base.DbTestCase):
                 task.node)
             mock_node_power_action.assert_called_once_with(task, states.REBOOT)
 
+    def test_update_firmware_invalid_args(self):
+        with task_manager.acquire(self.context, self.node.uuid,
+                                  shared=False) as task:
+            self.assertRaises(
+                exception.InvalidParameterValue,
+                task.driver.management.update_firmware,
+                task, [{'urlX': 'test1'}, {'url': 'test2'}])
+
     @mock.patch.object(task_manager, 'acquire', autospec=True)
     def test__query_firmware_update_failed(self, mock_acquire):
         driver_internal_info = {
diff --git a/releasenotes/notes/fix-redfish-firmware-images-validation-9b5b2fd28314ce66.yaml b/releasenotes/notes/fix-redfish-firmware-images-validation-9b5b2fd28314ce66.yaml
new file mode 100644
index 0000000000..21ee1b9496
--- /dev/null
+++ b/releasenotes/notes/fix-redfish-firmware-images-validation-9b5b2fd28314ce66.yaml
@@ -0,0 +1,8 @@
+---
+fixes:
+  - |
+    Fixes validation of input argument ``firmware_images`` of ``redfish``
+    hardware type clean step ``update_firmware``. Now it validates the argument
+    at the beginning of clean step. Prior to this fix issues were determined
+    at the time of executing firmware update or not at all (for example,
+    mistyping optional field 'wait').