diff --git a/base/mk/spec-platform_rpi.mk b/base/mk/spec-platform_rpi.mk
index c1712b6a53..aa1a2a9c29 100644
--- a/base/mk/spec-platform_rpi.mk
+++ b/base/mk/spec-platform_rpi.mk
@@ -5,7 +5,7 @@
#
# denote wich specs are also fullfilled by this spec
-SPECS += arm_v6 pl011 usb
+SPECS += arm_v6 pl011 usb framebuffer
# add repository relative include paths
REP_INC_DIR += include/platform/rpi
diff --git a/os/include/platform/rpi/platform/framebuffer_info.h b/os/include/platform/rpi/platform/framebuffer_info.h
new file mode 100644
index 0000000000..a58c35f3bc
--- /dev/null
+++ b/os/include/platform/rpi/platform/framebuffer_info.h
@@ -0,0 +1,59 @@
+/*
+ * \brief Framebuffer info structure
+ * \author Norman Feske
+ * \date 2013-09-15
+ */
+
+/*
+ * Copyright (C) 2013 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _PLATFORM__FRAMEBUFFER_INFO_H_
+#define _PLATFORM__FRAMEBUFFER_INFO_H_
+
+#include
+
+namespace Platform {
+ using namespace Genode;
+ struct Framebuffer_info;
+}
+
+
+/**
+ * Structure used by the protocol between the Videocore GPU and the ARM CPU for
+ * setting up the framebuffer via the mbox.
+ */
+struct Platform::Framebuffer_info
+{
+ uint32_t phys_width;
+ uint32_t phys_height;
+ uint32_t virt_width;
+ uint32_t virt_height;
+ uint32_t pitch = 0;
+ uint32_t depth;
+ uint32_t x_offset = 0;
+ uint32_t y_offset = 0;
+ uint32_t addr = 0;
+ uint32_t size = 0;
+
+ /**
+ * Default constructor needed to make the object transferable via RPC
+ */
+ Framebuffer_info()
+ :
+ phys_width(0), phys_height(0), virt_width(0), virt_height(),
+ depth(0)
+ { }
+
+ Framebuffer_info(uint32_t width, uint32_t height, uint32_t depth)
+ :
+ phys_width(width), phys_height(height),
+ virt_width(width), virt_height(height),
+ depth(depth)
+ { }
+};
+
+#endif /* _PLATFORM__FRAMEBUFFER_INFO_H_ */
diff --git a/os/include/platform/rpi/platform/property_message.h b/os/include/platform/rpi/platform/property_message.h
new file mode 100644
index 0000000000..08e09437d4
--- /dev/null
+++ b/os/include/platform/rpi/platform/property_message.h
@@ -0,0 +1,226 @@
+/*
+ * \brief Marshalling of mbox messages for property channel
+ * \author Norman Feske
+ * \date 2013-09-15
+ */
+
+/*
+ * Copyright (C) 2013 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _PLATFORM__PROPERTY_MESSAGE_H_
+#define _PLATFORM__PROPERTY_MESSAGE_H_
+
+/* Genode includes */
+#include
+#include
+
+/* board-specific includes */
+#include
+
+namespace Platform {
+ using namespace Genode;
+ struct Property_message;
+}
+
+
+/**
+ * Mailbox message buffer for the property channel
+ *
+ * This data structure is overlayed with memory shared with the VC. It
+ * contains a header, followed by a sequence of so-called command tags, wrapped
+ * up by a zero as an end marker.
+ */
+struct Platform::Property_message
+{
+ uint32_t buf_size;
+
+ enum Code { REQUEST = 0,
+ RESPONSE_SUCCESS = 0x80000000 };
+
+ Code code = REQUEST;
+
+ /*
+ * Start of the buffer that contains a sequence of tags
+ */
+ char buffer[];
+
+ /*
+ * There must be no member variables after this point
+ */
+
+ /*
+ * Each tag consists of a header, a part with request arguments, and a
+ * part with responses.
+ */
+ template
+ struct Tag
+ {
+ uint32_t const opcode;
+
+ /**
+ * Size of tag buffer
+ */
+ uint32_t const buf_size;
+
+ /**
+ * Size of request part of the tag
+ *
+ * The value is never changed locally. Therefore, it is declared as
+ * const. However, it will be updated by the VC. So we declare it
+ * volatile, too.
+ */
+ uint32_t volatile const len;
+
+ char payload[];
+
+ /**
+ * Utility for returning a response size of a tag type
+ *
+ * Depending on the presence of a 'TAG::Response' type, we need to
+ * return the actual size of the response (if the type is present) or
+ * 0. Both overloads are called with a compliant parameter 0. But only
+ * if 'T::Response' exists, the first overload is selected.
+ *
+ * SFINAE to the rescue!
+ */
+ template
+ static size_t response_size(typename T::Response *)
+ {
+ return sizeof(typename T::Response);
+ }
+
+ template
+ static size_t response_size(...)
+ {
+ return 0;
+ }
+
+ template
+ static size_t request_size(typename T::Request *)
+ {
+ return sizeof(typename T::Request);
+ }
+
+ template
+ static size_t request_size(...)
+ {
+ return 0;
+ }
+
+ template
+ struct Placeable : T
+ {
+ template
+ Placeable(ARGS... args) : T(args...) { }
+
+ inline void *operator new (size_t, void *ptr) { return ptr; }
+ };
+
+ template
+ void construct_request(typename T::Request *, ARGS... args)
+ {
+ new ((typename T::Request *)payload)
+ Placeable(args...);
+ }
+
+ template
+ void construct_request(...) { }
+
+ template
+ void construct_response(typename T::Response *)
+ {
+ new (payload) Placeable;
+ }
+
+ template
+ void construct_response(...) { }
+
+ static constexpr size_t payload_size()
+ {
+ return max(request_size(0), response_size(0));
+ }
+
+ template
+ Tag(REQUEST_ARGS... request_args)
+ :
+ opcode(TAG::opcode()),
+ buf_size(payload_size()),
+ len(request_size(0))
+ {
+ /*
+ * The order is important. If we called 'construct_response' after
+ * 'construct_request', we would overwrite the request parameters
+ * with the default response.
+ */
+ construct_response(0);
+ construct_request(0, request_args...);
+ }
+
+ inline void *operator new (size_t, void *ptr) { return ptr; }
+ };
+
+ void reset()
+ {
+ buf_size = 0;
+ code = REQUEST;
+ }
+
+ /**
+ * \return reference to tag in the message buffer
+ */
+ template
+ typename POLICY::Response const &append(REQUEST_ARGS... request_args)
+ {
+ auto *tag = new (buffer + buf_size) Tag(request_args...);
+
+ buf_size += sizeof(Tag) + Tag::payload_size();
+
+ return *(typename POLICY::Response *)tag->payload;
+ }
+
+ template
+ void append_no_response(REQUEST_ARGS... request_args)
+ {
+ new (buffer + buf_size) Tag(request_args...);
+
+ buf_size += sizeof(Tag) + Tag::payload_size();
+ }
+
+ void finalize()
+ {
+ /* append end tag */
+ *(uint32_t *)(buffer + buf_size) = 0;
+ buf_size += sizeof(uint32_t);
+ }
+
+ static unsigned channel() { return 8; }
+
+ static Board_base::Videocore_cache_policy cache_policy()
+ {
+ return Board_base::NON_COHERENT; /* for channel 8 only */
+ }
+
+ void dump(char const *label)
+ {
+ unsigned const *buf = (unsigned *)this;
+ printf("%s message:\n", label);
+ for (unsigned i = 0;; i++) {
+ for (unsigned j = 0; j < 8; j++) {
+ unsigned const msg_word_idx = i*8 + j;
+ printf(" %08x", buf[msg_word_idx]);
+ if (msg_word_idx*sizeof(unsigned) < buf_size)
+ continue;
+ printf("\n");
+ return;
+ }
+ }
+ }
+
+ inline void *operator new (size_t, void *ptr) { return ptr; }
+};
+
+#endif /* _PLATFORM__PROPERTY_MESSAGE_H_ */
diff --git a/os/include/platform/rpi/platform_session/client.h b/os/include/platform/rpi/platform_session/client.h
new file mode 100644
index 0000000000..8971de4192
--- /dev/null
+++ b/os/include/platform/rpi/platform_session/client.h
@@ -0,0 +1,38 @@
+/*
+ * \brief Raspberry Pi specific platform session client side
+ * \author Norman Feske
+ * \date 2013-09-16
+ */
+
+/*
+ * Copyright (C) 2013 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _INCLUDE__PLATFORM_SESSION__CLIENT_H_
+#define _INCLUDE__PLATFORM_SESSION__CLIENT_H_
+
+#include
+#include
+#include
+
+namespace Platform { struct Client; }
+
+struct Platform::Client : Genode::Rpc_client
+{
+ explicit Client(Capability session)
+ : Genode::Rpc_client(session) { }
+
+ void setup_framebuffer(Framebuffer_info &info) {
+ call(info); }
+
+ bool power_state(Power power) {
+ return call(power); }
+
+ void power_state(Power power, bool enable) {
+ call(power, enable); }
+};
+
+#endif /* _INCLUDE__PLATFORM_SESSION__CLIENT_H_ */
diff --git a/os/include/platform/rpi/platform_session/platform_session.h b/os/include/platform/rpi/platform_session/platform_session.h
new file mode 100644
index 0000000000..1a305b5564
--- /dev/null
+++ b/os/include/platform/rpi/platform_session/platform_session.h
@@ -0,0 +1,76 @@
+/*
+ * \brief Raspberry Pi specific platform session
+ * \author Norman Feske
+ * \date 2013-09-16
+ */
+
+/*
+ * Copyright (C) 2013 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _INCLUDE__PLATFORM_SESSION__PLATFORM_SESSION_H_
+#define _INCLUDE__PLATFORM_SESSION__PLATFORM_SESSION_H_
+
+#include
+#include
+#include
+#include
+
+namespace Platform {
+ using namespace Genode;
+ struct Session;
+}
+
+
+struct Platform::Session : Genode::Session
+{
+ static const char *service_name() { return "Platform"; }
+
+ /**
+ * Setup framebuffer
+ *
+ * The 'info' argument serves as both input and output parameter. As input,
+ * it describes the desired properties of the framebuffer. In return, the
+ * function delivers the values that were actually taken into effect.
+ */
+ virtual void setup_framebuffer(Framebuffer_info &info) = 0;
+
+ enum Power {
+ POWER_SDHCI = 0,
+ POWER_UART0 = 1,
+ POWER_UART1 = 2,
+ POWER_USB_HCD = 3,
+ POWER_I2C0 = 4,
+ POWER_I2C1 = 5,
+ POWER_I2C2 = 6,
+ POWER_SPI = 7,
+ POWER_CCP2TX = 8,
+ };
+
+ /**
+ * Request power state
+ */
+ virtual bool power_state(Power) = 0;
+
+ /**
+ * Set power state
+ */
+ virtual void power_state(Power, bool enable) = 0;
+
+
+ /*********************
+ ** RPC declaration **
+ *********************/
+
+ GENODE_RPC(Rpc_setup_framebuffer, void, setup_framebuffer, Framebuffer_info &);
+ GENODE_RPC(Rpc_get_power_state, bool, power_state, Power);
+ GENODE_RPC(Rpc_set_power_state, void, power_state, Power, bool);
+
+ GENODE_RPC_INTERFACE(Rpc_setup_framebuffer, Rpc_set_power_state,
+ Rpc_get_power_state);
+};
+
+#endif /* _INCLUDE__PLATFORM_SESSION__PLATFORM_SESSION_H_ */
diff --git a/os/src/drivers/framebuffer/rpi/main.cc b/os/src/drivers/framebuffer/rpi/main.cc
new file mode 100644
index 0000000000..7e593fefd3
--- /dev/null
+++ b/os/src/drivers/framebuffer/rpi/main.cc
@@ -0,0 +1,98 @@
+/*
+ * \brief Framebuffer driver for Raspberry Pi
+ * \author Norman Feske
+ * \date 2013-09-14
+ */
+
+/*
+ * Copyright (C) 2013 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace Framebuffer {
+ using namespace Genode;
+ class Session_component;
+};
+
+
+class Framebuffer::Session_component : public Genode::Rpc_object
+{
+ private:
+
+ size_t const _width;
+ size_t const _height;
+ Attached_io_mem_dataspace _fb_mem;
+
+ public:
+
+ Session_component(addr_t phys_addr, size_t size, size_t width, size_t height)
+ :
+ _width(width), _height(height), _fb_mem(phys_addr, size)
+ { }
+
+ /************************************
+ ** Framebuffer::Session interface **
+ ************************************/
+
+ Dataspace_capability dataspace() { return _fb_mem.cap(); }
+
+ void release() { }
+
+ Mode mode() const
+ {
+ return Mode(_width, _height, Mode::RGB565);
+ }
+
+ void mode_sigh(Genode::Signal_context_capability) { }
+
+ void refresh(int, int, int, int) { }
+};
+
+
+int main(int, char **)
+{
+ using namespace Framebuffer;
+ using namespace Genode;
+
+ printf("--- fb_drv started ---\n");
+
+ static Platform::Connection platform;
+
+ Platform::Framebuffer_info fb_info(1024, 768, 16);
+ platform.setup_framebuffer(fb_info);
+
+ /*
+ * Initialize server entry point
+ */
+ enum { STACK_SIZE = 4096 };
+ static Cap_connection cap;
+ static Rpc_entrypoint ep(&cap, STACK_SIZE, "fb_ep");
+
+ /*
+ * Let the entry point serve the framebuffer session and root interfaces
+ */
+ static Session_component fb_session(fb_info.addr,
+ fb_info.size,
+ fb_info.phys_width,
+ fb_info.phys_height);
+ static Static_root fb_root(ep.manage(&fb_session));
+
+ /*
+ * Announce service
+ */
+ env()->parent()->announce(ep.manage(&fb_root));
+
+ sleep_forever();
+ return 0;
+}
diff --git a/os/src/drivers/framebuffer/rpi/target.mk b/os/src/drivers/framebuffer/rpi/target.mk
new file mode 100644
index 0000000000..12d1f93de1
--- /dev/null
+++ b/os/src/drivers/framebuffer/rpi/target.mk
@@ -0,0 +1,8 @@
+TARGET = fb_drv
+REQUIRES = platform_rpi
+SRC_CC = main.cc
+LIBS = base
+INC_DIR += $(PRG_DIR)
+
+# enable C++11 support
+CC_CXX_OPT += -std=gnu++11
diff --git a/os/src/drivers/platform/rpi/framebuffer_message.h b/os/src/drivers/platform/rpi/framebuffer_message.h
new file mode 100644
index 0000000000..62ab7843dc
--- /dev/null
+++ b/os/src/drivers/platform/rpi/framebuffer_message.h
@@ -0,0 +1,64 @@
+/*
+ * \brief Marshalling of mbox messages for framebuffer channel
+ * \author Norman Feske
+ * \date 2013-09-15
+ */
+
+/*
+ * Copyright (C) 2013 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _FRAMEBUFFER_MESSAGE_H_
+#define _FRAMEBUFFER_MESSAGE_H_
+
+/* Genode includes */
+#include
+#include
+
+/* board-specific includes */
+#include
+#include
+
+namespace Platform { struct Framebuffer_message; }
+
+
+/**
+ * Mailbox message buffer for the framebuffer channel
+ */
+struct Platform::Framebuffer_message : Framebuffer_info
+{
+ Framebuffer_message(Framebuffer_info const &info) : Framebuffer_info(info) { }
+
+ void finalize() { }
+
+ static unsigned channel() { return 1; }
+
+ static Genode::Board_base::Videocore_cache_policy cache_policy()
+ {
+ return Genode::Board_base::COHERENT;
+ }
+
+ void dump(char const *label)
+ {
+ using Genode::printf;
+
+ printf("%s message:\n", label);
+ printf(" phys_width: %u\n", phys_width);
+ printf(" phys_height: %u\n", phys_height);
+ printf(" virt_width: %u\n", virt_width);
+ printf(" virt_height: %u\n", virt_height);
+ printf(" pitch: %u\n", pitch);
+ printf(" depth: %d\n", depth);
+ printf(" x_offset: %d\n", x_offset);
+ printf(" y_offset: %d\n", y_offset);
+ printf(" addr: 0x%08x\n", addr);
+ printf(" size: 0x%08x\n", size);
+ }
+
+ inline void *operator new (Genode::size_t, void *ptr) { return ptr; }
+};
+
+#endif /* _FRAMEBUFFER_MESSAGE_H_ */
diff --git a/os/src/drivers/platform/rpi/main.cc b/os/src/drivers/platform/rpi/main.cc
new file mode 100644
index 0000000000..e25da65027
--- /dev/null
+++ b/os/src/drivers/platform/rpi/main.cc
@@ -0,0 +1,110 @@
+/*
+ * \brief Driver for Raspberry Pi specific platform devices
+ * \author Norman Feske
+ * \date 2013-09-16
+ */
+
+/*
+ * Copyright (C) 2013 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+
+/* platform includes */
+#include
+#include
+
+/* local includes */
+#include
+#include
+#include
+
+
+namespace Platform {
+ class Session_component;
+ class Root;
+}
+
+
+class Platform::Session_component : public Genode::Rpc_object
+{
+ private:
+
+ Mbox &_mbox;
+
+ public:
+
+ /**
+ * Constructor
+ */
+ Session_component(Mbox &mbox) : _mbox(mbox) { }
+
+
+ /**********************************
+ ** Platform session interface **
+ **********************************/
+
+ void setup_framebuffer(Framebuffer_info &info)
+ {
+ auto const &msg = _mbox.message(info);
+ _mbox.call();
+ info = msg;
+ }
+
+ bool power_state(Power id)
+ {
+ auto &msg = _mbox.message();
+ auto const &res = msg.append(id);
+ _mbox.call();
+ return res.state;
+ }
+
+ void power_state(Power id, bool enable)
+ {
+ auto &msg = _mbox.message();
+ msg.append_no_response(id, enable, true);
+ _mbox.call();
+ }
+};
+
+
+class Platform::Root : public Genode::Root_component
+{
+ private:
+
+ Mbox _mbox;
+
+ protected:
+
+ Session_component *_create_session(const char *args) {
+ return new (md_alloc()) Session_component(_mbox); }
+
+ public:
+
+ Root(Rpc_entrypoint *session_ep, Allocator *md_alloc)
+ : Root_component(session_ep, md_alloc) { }
+};
+
+
+int main(int, char **)
+{
+ using namespace Platform;
+
+ PINF("--- Raspberry Pi platform driver ---\n");
+
+ static Cap_connection cap;
+ static Rpc_entrypoint ep(&cap, 4096, "rpi_plat_ep");
+ static Platform::Root plat_root(&ep, env()->heap());
+ env()->parent()->announce(ep.manage(&plat_root));
+
+ sleep_forever();
+ return 0;
+}
diff --git a/os/src/drivers/platform/rpi/mbox.h b/os/src/drivers/platform/rpi/mbox.h
new file mode 100644
index 0000000000..d35f010a62
--- /dev/null
+++ b/os/src/drivers/platform/rpi/mbox.h
@@ -0,0 +1,118 @@
+/*
+ * \brief Mbox for communicating between Videocore and ARM
+ * \author Norman Feske
+ * \date 2013-09-14
+ */
+
+/*
+ * Copyright (C) 2013 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _MBOX_H_
+#define _MBOX_H_
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+class Mbox : Genode::Attached_mmio
+{
+ private:
+
+ enum { verbose = false };
+
+ typedef Genode::addr_t addr_t;
+ typedef Genode::uint32_t uint32_t;
+ typedef Genode::Dataspace_client Dataspace_client;
+
+ enum { BASE = 0x2000b800,
+ SIZE = 0x100 };
+
+ struct Read : Register<0x80, 32> { };
+
+ struct Status : Register<0x98, 32>
+ {
+ struct Rd_empty : Bitfield<30, 1> { };
+ struct Wr_full : Bitfield<31, 1> { };
+ };
+
+ struct Write : Register<0xa0, 32>
+ {
+ struct Channel : Bitfield<0, 4> { };
+ struct Value : Bitfield<4, 26> { };
+ struct Cache_policy : Bitfield<30, 2> { };
+ };
+
+ enum { MSG_BUFFER_SIZE = 0x1000 };
+ Genode::Attached_ram_dataspace _msg_buffer = { Genode::env()->ram_session(),
+ MSG_BUFFER_SIZE };
+
+ addr_t const _msg_phys = { Dataspace_client(_msg_buffer.cap()).phys_addr() };
+
+ struct Delayer : Mmio::Delayer
+ {
+ Timer::Connection timer;
+ void usleep(unsigned us) { timer.usleep(us); }
+ } _delayer;;
+
+ template
+ MESSAGE &_message()
+ {
+ return *_msg_buffer.local_addr();
+ }
+
+ public:
+
+ Mbox() : Genode::Attached_mmio(BASE, SIZE) { }
+
+ /**
+ * Return reference to typed message buffer
+ */
+ template
+ MESSAGE &message(ARGS... args)
+ {
+ return *(new (_msg_buffer.local_addr()) MESSAGE(args...));
+ }
+
+ template
+ void call()
+ {
+ _message().finalize();
+
+ if (verbose)
+ _message().dump("Input");
+
+ /* flush pending data in the read buffer */
+ while (!read())
+ read();
+
+ if (!wait_for(0, _delayer, 500, 1)) {
+ PERR("Mbox: timeout waiting for ready-to-write");
+ return;
+ }
+
+ Write::access_t value = 0;
+ Write::Channel:: set(value, MESSAGE::channel());
+ Write::Value:: set(value, _msg_phys >> Write::Value::SHIFT);
+ Write::Cache_policy::set(value, MESSAGE::cache_policy());
+ write(value);
+
+ if (!wait_for(0, _delayer, 500, 1)) {
+ PERR("Mbox: timeout waiting for response");
+ return;
+ }
+
+ if (verbose)
+ _message().dump("Output");
+ }
+};
+
+#endif /* _MBOX_H_ */
diff --git a/os/src/drivers/platform/rpi/property_command.h b/os/src/drivers/platform/rpi/property_command.h
new file mode 100644
index 0000000000..e9be42503a
--- /dev/null
+++ b/os/src/drivers/platform/rpi/property_command.h
@@ -0,0 +1,115 @@
+/*
+ * \brief Command definitions for the property mbox channel
+ * \author Norman Feske
+ * \date 2013-09-15
+ */
+
+/*
+ * Copyright (C) 2013 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _PROPERTY_COMMAND_H_
+#define _PROPERTY_COMMAND_H_
+
+/* Genode includes */
+#include
+
+namespace Property_command {
+
+ using namespace Genode;
+
+ struct Get_power_state
+ {
+ static uint32_t opcode() { return 0x00020001; };
+
+ struct Request
+ {
+ uint32_t const device_id;
+
+ Request(uint32_t device_id) : device_id(device_id) { }
+ };
+
+ struct Response
+ {
+ uint32_t const device_id;
+ uint32_t const state;
+ };
+ };
+
+ struct Set_power_state
+ {
+ static uint32_t opcode() { return 0x00028001; };
+
+ struct Request
+ {
+ uint32_t const device_id;
+ uint32_t const state;
+
+ Request(uint32_t device_id, bool enable, bool wait)
+ :
+ device_id(device_id),
+ state(enable | (wait << 1))
+ { }
+ };
+
+ struct Response
+ {
+ uint32_t const device_id;
+ uint32_t const state;
+ };
+ };
+
+ struct Allocate_buffer
+ {
+ static uint32_t opcode() { return 0x00040001; };
+
+ struct Request
+ {
+ uint32_t const alignment = 0x100;
+ };
+
+ struct Response
+ {
+ uint32_t const address = 0;
+ uint32_t const size = 0;
+ };
+ };
+
+
+ struct Release_buffer
+ {
+ static uint32_t opcode() { return 0x00048001; };
+ };
+
+
+ struct Get_physical_w_h
+ {
+ static uint32_t opcode() { return 0x00040003; };
+
+ struct Response
+ {
+ uint32_t const width = 0;
+ uint32_t const height = 0;
+ };
+ };
+
+
+ struct Set_physical_w_h
+ {
+ static uint32_t opcode() { return 0x00048003; };
+
+ struct Request
+ {
+ uint32_t const width;
+ uint32_t const height;
+
+ Request(uint32_t width, uint32_t height)
+ : width(width), height(height) { }
+ };
+ };
+}
+
+#endif /* _PROPERTY_COMMAND_H_ */
diff --git a/os/src/drivers/platform/rpi/target.mk b/os/src/drivers/platform/rpi/target.mk
new file mode 100644
index 0000000000..887e77fa19
--- /dev/null
+++ b/os/src/drivers/platform/rpi/target.mk
@@ -0,0 +1,8 @@
+TARGET = platform_drv
+REQUIRES = platform_rpi
+SRC_CC = main.cc
+INC_DIR += ${PRG_DIR}
+LIBS = base
+
+# enable C++11 support
+CC_CXX_OPT += -std=gnu++11