pnor_partition: Handle requests exceeding partition's actual size

Partitions with patch files whose size was less than the partition size
in the ToC could not be completely read by the host. For example when
scanning over the entire PNOR on the host with `cat /dev/mtd0 >
/dev/null` the host would lock up. A trace from mboxd under these
circumstances shows:

    [ 1519832857.966501396] Received MBOX command: 4
    [ 1519832857.966695620] Host requested flash @ 0x02a44000
    [ 1519832857.968642020] Window @ 0x730ce000 for size 0x00024000 maps flash offset 0x02a44000
    [ 1519832857.968808728] Writing MBOX response: 1
    [ 1519832858.222090630] Received MBOX command: 4
    [ 1519832858.222284692] Host requested flash @ 0x02a68000
    [ 1519832858.223964544] Window @ 0x73cce000 for size 0x00009000 maps flash offset 0x02a68000
    [ 1519832858.224136142] Writing MBOX response: 1
    [ 1519832858.435944292] Received MBOX command: 4
    [ 1519832858.436138394] Host requested flash @ 0x02a71000
    [ 1519832858.437026725] Window @ 0x734ce000 for size 0x00007000 maps flash offset 0x02a71000
    [ 1519832858.437195251] Writing MBOX response: 1
    [ 1519832858.646768070] Received MBOX command: 4
    [ 1519832858.646968637] Host requested flash @ 0x02a78000
    [ 1519832858.647567228] Window @ 0x768ce000 for size 0x00001000 maps flash offset 0x02a78000
    [ 1519832858.647731755] Writing MBOX response: 1
    [ 1519832858.848288015] Received MBOX command: 4
    [ 1519832858.848489188] Host requested flash @ 0x02a79000
    [ 1519832858.849006404] Window @ 0x758ce000 for size 0x00000000 maps flash offset 0x02a79000
    [ 1519832858.849168870] Writing MBOX response: 1
    [ 1519832859.048631708] Received MBOX command: 4
    [ 1519832859.048827305] Host requested flash @ 0x02a79000
    [ 1519832859.049343956] Window @ 0x756ce000 for size 0x00000000 maps flash offset 0x02a79000
    [ 1519832859.049503553] Writing MBOX response: 1
    [ 1519832859.248950916] Received MBOX command: 4
    [ 1519832859.249142069] Host requested flash @ 0x02a79000
    [ 1519832859.249649871] Window @ 0x741ce000 for size 0x00000000 maps flash offset 0x02a79000

Of significance are the last three CREATE_READ_WINDOW requests, where
the request succeeds but mboxd reports back a zero-sized window to the
host. The host immediately considers itself done with the window, and
requests a new window offset from the previous by size, which is zero.
Thus it re-requests the same offset, and receives the same zero-sized
window in return.

As a result, firmware gets stuck in an unterminated loop, stealing the
core from Linux, which promptly starts reporting a constant stream of
RCU stall warnings among the rest of the failures. Everyone is
miserable.

The offset in question maps to a partition but not to a valid offset in
the file backing that partition. Resize the backing file to meet the
maximum access address within the limits of the partition size defined
in the ToC. By doing so, we are able to map as much of the partition as
necessary.

However, we're not done. Whilst we no longer crash the host, we still
don't successfully complete the operation the host requested. From
Petitboot:

    / # cat /dev/mtd0 > /dev/null
    [  501.061616288,3] MBOX-FLASH: Bad response code from BMC 2
    [  501.150405995,3] MBOX-FLASH: Error waiting for BMC
    cat: read error: Input/output error
    / # echo $?
    1
    / #

And the corresponding mboxd trace on the BMC:

    [ 1519966031.652036815] Received MBOX command: 4
    [ 1519966031.652272613] Host requested flash @ 0x03f1a000
    [ 1519966031.652411603] Tried to open read window past flash limit
    [ 1519966031.652500088] Couldn't create window mapping for offset 0x03f1a000
    [ 1519966031.652607966] Error handling mbox cmd: 4
    [ 1519966031.652661421] Writing MBOX response: 2
    [ 1519966031.652762229] Error handling MBOX event

The read failure will be fixed in a follow-up patch.

Change-Id: Iffdfb8af6f739df5e6d9c171b584a7244bdb7099
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
5 files changed
tree: 6bba6e8bf0a9eb18f87ecf937bf1224d5e6c18a3
  1. Documentation/
  2. m4/
  3. test/
  4. xyz/
  5. .clang-format-c
  6. .clang-format-c++
  7. .gitignore
  8. bootstrap.sh
  9. common.c
  10. common.h
  11. configure.ac
  12. dbus.h
  13. format-code.sh
  14. LICENSE
  15. Makefile.am
  16. mbox.h
  17. mboxctl.c
  18. mboxd.c
  19. mboxd_dbus.c
  20. mboxd_dbus.h
  21. mboxd_flash.h
  22. mboxd_flash_physical.c
  23. mboxd_flash_virtual.cpp
  24. mboxd_lpc.c
  25. mboxd_lpc.h
  26. mboxd_lpc_physical.c
  27. mboxd_lpc_virtual.cpp
  28. mboxd_msg.c
  29. mboxd_msg.h
  30. mboxd_pnor_partition_table.cpp
  31. mboxd_pnor_partition_table.h
  32. mboxd_windows.c
  33. mboxd_windows.h
  34. mtd.c
  35. pnor_partition.cpp
  36. pnor_partition.hpp
  37. pnor_partition_defs.h
  38. pnor_partition_table.cpp
  39. pnor_partition_table.hpp
  40. README.md
README.md

Copyright 2017 IBM

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.

MBOX

This repo contains the protocol definition for the host to BMC mailbox communication specification which can be found in Documentation/mbox_procotol.md.

There is also a reference implementation of a BMC mailbox daemon, the details of which can be found in Documentation/mboxd.md.

Finally there is also an implementation of a mailbox daemon control program, the details of which can be found in Documentation/mboxctl.md.

Style Guide

Preamble

This codebase is a mix of C (due to its heritage) and C++. This is an ugly split: message logging and error handling can be vastly different inside the same codebase. The aim is to remove the split one way or the other over time and have consistent approaches to solving problems.

phosphor-mboxd is developed as part of the OpenBMC project, which also leads to integration of frameworks such as phosphor-logging. Specifically on phosphor-logging, it's noted that without care we can achieve absurd duplication or irritating splits in where errors are reported, as the C code is not capable of making use of the interfaces provided.

Rules

  1. Message logging MUST be done to stdout or stderr, and MUST NOT be done directly via journal APIs or wrappers of the journal APIs.

    Rationale:

    We have two scenarios where we care about output, with the important restriction that the method must be consistent between C and C++:

    1. Running in-context on an OpenBMC-based system
    2. Running the test suite

    In the first case it is desirable that the messages appear in the system journal. To this end, systemd will by default capture stdout and stderr of the launched binary and redirect it to the journal.

    In the second case it is desirable that messages be captured by the test runner (make check) for test failure analysis, and it is undesirable for messages to appear in the system journal (as these are tests, not issues affecting the health of the system they are being executed on).

    Therefore direct calls to the journal MUST be avoided for the purpose of message logging.

    Note: This section specifically targets the use of phosphor-logging's log<T>(). It does not prevent the use of elog<T>().