1 #include "config.h"
2 
3 extern "C" {
4 #include "mbox.h"
5 #include "mboxd_msg.h"
6 };
7 
8 #include "vpnor/mboxd_msg.hpp"
9 #include "vpnor/pnor_partition_table.hpp"
10 
11 // clang-format off
12 const mboxd_mbox_handler vpnor_mbox_handlers[NUM_MBOX_CMDS] =
13 {
14 	mbox_handle_reset,
15 	mbox_handle_mbox_info,
16 	mbox_handle_flash_info,
17 	mbox_handle_read_window,
18 	mbox_handle_close_window,
19 	vpnor_handle_write_window,
20 	mbox_handle_dirty_window,
21 	mbox_handle_flush_window,
22 	mbox_handle_ack,
23 	mbox_handle_erase_window
24 };
25 // clang-format on
26 
27 /* XXX: Maybe this should be a method on a class? */
vpnor_partition_is_readonly(const pnor_partition & part)28 static bool vpnor_partition_is_readonly(const pnor_partition& part)
29 {
30     return part.data.user.data[1] & PARTITION_READONLY;
31 }
32 
vpnor_handle_write_window(struct mbox_context * context,union mbox_regs * req,struct mbox_msg * resp)33 int vpnor_handle_write_window(struct mbox_context* context,
34                               union mbox_regs* req, struct mbox_msg* resp)
35 {
36     size_t offset = get_u16(&req->msg.args[0]);
37     offset <<= context->block_size_shift;
38     try
39     {
40         const pnor_partition& part = context->vpnor->table->partition(offset);
41         if (vpnor_partition_is_readonly(part))
42         {
43             return -MBOX_R_WINDOW_ERROR;
44         }
45     }
46     catch (const openpower::virtual_pnor::UnmappedOffset& e)
47     {
48         /*
49          * Writes to unmapped areas are not meaningful, so deny the request.
50          * This removes the ability for a compromised host to abuse unused
51          * space if any data was to be persisted (which it isn't).
52          */
53         return -MBOX_R_WINDOW_ERROR;
54     }
55 
56     /* Defer to the default handler */
57     return mbox_handle_write_window(context, req, resp);
58 }
59