l4re-base-25.08.0

This commit is contained in:
2025-09-12 15:55:45 +02:00
commit d959eaab98
37938 changed files with 9382688 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
L4DIR ?= ../..
include $(L4DIR)/mk/project.mk

View File

@@ -0,0 +1,2 @@
requires: stdlibs
Maintainer: adam@os.inf.tu-dresden.de

View File

@@ -0,0 +1,7 @@
PKGDIR ?= .
L4DIR ?= $(PKGDIR)/../../..
TARGET = src configs
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ../..
L4DIR ?= $(PKGDIR)/../..
PKGNAME = ex_clntsrv
SRC_ASSETS_NED = clntsrv.cfg
SRC_ASSETS_MODLIST = modules.list
include $(L4DIR)/mk/assets.mk

View File

@@ -0,0 +1,21 @@
-- vim:set ft=lua:
-- Include L4 functionality
local L4 = require("L4");
-- Some shortcut for less typing
local ld = L4.default_loader;
-- Channel for the two programs to talk to each other.
local calc_server = ld:new_channel();
-- The server program, getting the channel in server mode.
ld:start({ caps = { calc_server = calc_server:svr() },
log = { "server", "blue" } },
"rom/ex_clntsrv-server");
-- The client program, getting the 'calc_server' channel to be able to talk
-- to the server. The client will be started with a green log output.
ld:start({ caps = { calc_server = calc_server },
log = { "client", "green" } },
"rom/ex_clntsrv-client");

View File

@@ -0,0 +1,8 @@
entry ex_clntsrv
roottask moe rom/clntsrv.cfg
module l4re
module ned
module ex_clntsrv-server
module ex_clntsrv-client
module ned/ex_clntsrv/clntsrv.cfg

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_clntsrv-server ex_clntsrv-client
SRC_CC_ex_clntsrv-server = server.cc
SRC_CC_ex_clntsrv-client = client.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,48 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/sys/err.h>
#include <l4/sys/types.h>
#include <l4/re/env>
#include <l4/re/util/cap_alloc>
#include <stdio.h>
#include "shared.h"
int
main()
{
L4::Cap<Calc> server = L4Re::Env::env()->get_cap<Calc>("calc_server");
if (!server.is_valid())
{
printf("Could not get server capability!\n");
return 1;
}
l4_uint32_t val1 = 8;
l4_uint32_t val2 = 5;
printf("Asking for %d - %d\n", val1, val2);
if (server->sub(val1, val2, &val1))
{
printf("Error talking to server\n");
return 1;
}
printf("Result of subtract call: %d\n", val1);
printf("Asking for -%d\n", val1);
if (server->neg(val1, &val1))
{
printf("Error talking to server\n");
return 1;
}
printf("Result of negate call: %d\n", val1);
return 0;
}

View File

@@ -0,0 +1,57 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <stdio.h>
#include <l4/re/env>
#include <l4/re/util/cap_alloc>
#include <l4/re/util/object_registry>
#include <l4/re/util/br_manager>
#include <l4/sys/cxx/ipc_epiface>
#include "shared.h"
static L4Re::Util::Registry_server<> server;
class Calculation_server : public L4::Epiface_t<Calculation_server, Calc>
{
public:
int op_sub(Calc::Rights, l4_uint32_t a, l4_uint32_t b, l4_uint32_t &res)
{
res = a - b;
return 0;
}
int op_neg(Calc::Rights, l4_uint32_t a, l4_uint32_t &res)
{
res = -a;
return 0;
}
};
int
main()
{
static Calculation_server calc;
// Register calculation server
if (!server.registry()->register_obj(&calc, "calc_server").is_valid())
{
printf("Could not register my service, is there a 'calc_server' in the caps table?\n");
return 1;
}
printf("Welcome to the calculation server!\n"
"I can do subtractions and negations.\n");
// Wait for client requests
server.loop();
return 0;
}

View File

@@ -0,0 +1,20 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/sys/capability>
#include <l4/sys/cxx/ipc_iface>
struct Calc : L4::Kobject_t<Calc, L4::Kobject, 0x44>
{
L4_INLINE_RPC(int, sub, (l4_uint32_t a, l4_uint32_t b, l4_uint32_t *res));
L4_INLINE_RPC(int, neg, (l4_uint32_t a, l4_uint32_t *res));
typedef L4::Typeid::Rpcs<sub_t, neg_t> Rpcs;
};

View File

@@ -0,0 +1,22 @@
# color, fractal, spectrum
optional: l4re_c-util
# color, fractal
optional: libgfxbitmap
# fractal
optional: libpthread
# present
optional: libl4png_wrap libl4revfs-fs-arfs
# sdl_waves
optional: libsdl
# spectrum, present
optional: libevent
# spectrum
optional: stdlibs
Maintainer: adam@os.inf.tu-dresden.de

View File

@@ -0,0 +1,6 @@
PKGDIR = .
L4DIR ?= $(PKGDIR)/../../..
TARGET = $(wildcard [a-z]*)
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,10 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_fb_spectrum_c ex_fb_spectrum_cc
SRC_CC_ex_fb_spectrum_cc = spectrum.cc
SRC_C_ex_fb_spectrum_c = spectrum_c.c
REQUIRES_LIBS = libevent l4re_c-util
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,192 @@
/* SPDX-License-Identifier: MIT */
/**
* \file
* \brief fb usage demo, with C and C++
* \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
**/
/* (c) 2010, Adam Lackorzynski
*/
/*
* Event handling in C mode has not been done.
*/
#ifdef DO_C
#include <l4/re/c/util/video/goos_fb.h>
#else
#include <l4/re/util/video/goos_fb>
#include <l4/sys/semaphore>
#include <l4/re/util/event>
#include <l4/event/event>
#endif
#include <l4/re/event_enums.h>
#include <l4/util/keymap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef DO_C
static l4re_util_video_goos_fb_t gfb;
static l4re_video_view_info_t fbi;
#else
static L4Re::Util::Video::Goos_fb gfb;
static L4Re::Video::View::Info fbi;
static L4Re::Util::Event event;
#endif
static void *fbmem_vaddr;
static unsigned bpp;
static void put_pixel(int x, int y, int fullval)
{
unsigned v = 0;
#ifdef DO_C
unsigned bpp = l4re_video_bits_per_pixel(&fbi.pixel_info);
unsigned long offset = (unsigned long)fbmem_vaddr + y * fbi.bytes_per_line + x * fbi.pixel_info.bytes_per_pixel;
v = ((fullval >> (8 - fbi.pixel_info.r.size)) & ((1 << fbi.pixel_info.r.size) - 1)) << fbi.pixel_info.r.shift;
v |= ((fullval >> (16 - fbi.pixel_info.g.size)) & ((1 << fbi.pixel_info.g.size) - 1)) << fbi.pixel_info.g.shift;
v |= ((fullval >> (24 - fbi.pixel_info.b.size)) & ((1 << fbi.pixel_info.b.size) - 1)) << fbi.pixel_info.b.shift;
#else
unsigned long offset = (unsigned long)fbmem_vaddr + y * fbi.bytes_per_line + x * fbi.pixel_info.bytes_per_pixel();
v = ((fullval >> (8 - fbi.pixel_info.r().size())) & ((1 << fbi.pixel_info.r().size()) - 1)) << fbi.pixel_info.r().shift();
v |= ((fullval >> (16 - fbi.pixel_info.g().size())) & ((1 << fbi.pixel_info.g().size()) - 1)) << fbi.pixel_info.g().shift();
v |= ((fullval >> (24 - fbi.pixel_info.b().size())) & ((1 << fbi.pixel_info.b().size()) - 1)) << fbi.pixel_info.b().shift();
#endif
switch (bpp)
{
case 8: *(unsigned char *)offset = v; break;
case 14: case 15: case 16: *(unsigned short *)offset = v; break;
case 24: case 32: *(unsigned int *)offset = v; break;
default:
printf("unhandled bitsperpixel %d\n", bpp);
};
}
static void update_rect(int x, int y, int w, int h)
{
#ifdef DO_C
l4re_util_video_goos_fb_refresh(&gfb, x, y, w, h);
#else
gfb.refresh(x, y, w, h);
#endif
}
static inline unsigned color_val(unsigned w, unsigned peak_point, unsigned val)
{
unsigned third = w / 3;
if (third == 0)
return 0;
unsigned a = abs((int)(val - peak_point));
if (a > third * 2)
a = peak_point + w - val;
if (a > third)
return 0;
return ((third - a) * 255) / third;
}
#ifndef DO_C
namespace {
struct Ev_loop : public Event::Event_loop
{
Ev_loop(L4::Cap<L4::Semaphore> irq, int prio) : Event::Event_loop(irq, prio) {}
void handle();
};
void Ev_loop::handle()
{
while (L4Re::Event_buffer::Event *e = event.buffer().next())
{
int k;
printf("Event: %16lld: %d %d %d\n",
e->time, e->payload.type, e->payload.code, e->payload.value);
if (e->payload.type == L4RE_EV_KEY
&& ((k = l4util_map_event_to_keymap(e->payload.code, 0)) >= 32))
printf(" key: %c\n", k);
// proper mouse and keyboard handling code comes here
e->free();
}
}
}
#endif
int main(void)
{
#ifndef DO_C
if (gfb.init("fb") < 0)
return 1;
if (gfb.view_info(&fbi))
return 2;
if (!(fbmem_vaddr = gfb.attach_buffer()))
return 3;
bpp = fbi.pixel_info.bits_per_pixel();
if (auto ev = L4::cap_dynamic_cast<L4Re::Event>(gfb.goos()))
{
if (event.init<L4::Semaphore>(ev))
return 4;
// use new so that Ev_loop survives this block
Ev_loop *event_hdl;
event_hdl = new Ev_loop(L4::cap_cast<L4::Semaphore>(event.irq()), 4);
if (!event_hdl->attached())
return 5;
event_hdl->start();
}
else
printf("Goos cap does not support event protocol, running without.\n");
#else
if (l4re_util_video_goos_fb_setup_name(&gfb, "fb"))
return 1;
if (l4re_util_video_goos_fb_view_info(&gfb, &fbi))
return 2;
if (!(fbmem_vaddr = l4re_util_video_goos_fb_attach_buffer(&gfb)))
return 3;
bpp = l4re_video_bits_per_pixel(&fbi.pixel_info);
#endif
printf("x:%ld y:%ld bit/pixel:%d bytes/line:%ld\n",
fbi.width, fbi.height, bpp, fbi.bytes_per_line);
// now some fancy stuff
unsigned w = fbi.width;
unsigned h = fbi.height;
unsigned t = w / 3;
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 100000000;
for (unsigned cnt = 0; ; cnt += 2)
{
for (unsigned y = 0; y < h; ++y)
for (unsigned x = 0; x < w; ++x)
{
unsigned r = color_val(w, 0 * t, (x + cnt) % w);
unsigned g = color_val(h, 1 * t, (y + (cnt >> 1)) % h);
unsigned b = color_val(w, 2 * t, (w - x + cnt) % w);
if (0)
printf("%3d: %3d:%3d:%3d\n", x, r, g, b);
put_pixel(x, y, (r << 0) | (g << 8) | (b << 16));
}
update_rect(0, 0, fbi.width, fbi.height);
nanosleep(&ts, NULL);
}
return 0;
}

View File

@@ -0,0 +1,2 @@
#define DO_C
#include "spectrum.cc"

View File

@@ -0,0 +1,9 @@
requires: stdlibs
# input, led, uart
optional: libstdc++ libio-vbus
# uart
requires: drivers_uart libio
Maintainer: adam@os.inf.tu-dresden.de

View File

@@ -0,0 +1,6 @@
PKGDIR = .
L4DIR ?= $(PKGDIR)/../../..
TARGET = input led uart configs
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,16 @@
# GPIO examples
This directory contains examples to showcase the features and the use of io's
GPIO subsystem.
## input
This example configures a GPIO pin as an interrupt source. To try this with
your hardware, connect the GPIO pin to ground. To issue the interrupt
disconnect it from ground.
## led
This example uses a GPIO pin to turn an LED on and off. Either your hardware
has a user-configurable LED connected via GPIO or you can easily build this on
your own using a bread board.

View File

@@ -0,0 +1,15 @@
PKGDIR ?= ../
L4DIR ?= $(PKGDIR)/../../..
SRC_ASSETS_MODLIST = ex_gpio.list
SRC_ASSETS_IO = gpio_input.vbus \
gpio_led.vbus \
gpio_uart.vbus \
$(patsubst $(SRC_DIR)/%,%,$(wildcard $(SRC_DIR)/plat-*/*.io))
SRC_ASSETS_NED = gpio_input.cfg \
gpio_led.cfg \
gpio_uart.cfg
include $(L4DIR)/mk/assets.mk

View File

@@ -0,0 +1,34 @@
# vim:set ft=l4mods:
default-kernel fiasco -serial_esc
entry ex_gpio_led
moe ned/gpio/gpio_led.cfg
module l4re
module ned
module io
module ex_gpio_led
module[fname=hw_devices.io,perl] "io/plat-$ENV{PLATFORM_TYPE}/hw_devices.io"
module[perl] "io/plat-$ENV{PLATFORM_TYPE}/gpio_led.io"
module io/gpio_led.vbus
entry ex_gpio_input
moe ned/gpio/gpio_input.cfg
module l4re
module ned
module io
module ex_gpio_input
module[fname=hw_devices.io,perl] "io/plat-$ENV{PLATFORM_TYPE}/hw_devices.io"
module[perl] "io/plat-$ENV{PLATFORM_TYPE}/gpio_input.io"
module io/gpio_input.vbus
entry ex_gpio_uart
moe ned/gpio/gpio_uart.cfg
module l4re
module ned
module io
module cons
module rpi_uart
module[fname=hw_devices.io,perl] "io/plat-$ENV{PLATFORM_TYPE}/hw_devices.io"
module[perl] "io/plat-$ENV{PLATFORM_TYPE}/gpio_uart.io"
module io/gpio_uart.vbus

View File

@@ -0,0 +1,33 @@
-- vi:ft=lua
local L4 = require "L4";
loader = L4.default_loader
local input_vbus = loader:new_channel();
loader:startv(
{
caps = {
icu = L4.Env.icu;
gpio_input_bus = input_vbus:svr();
sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0);
},
log = {"io", "red"}
},
"rom/io",
-- load base device file with the SoC's hardware devices
"rom/hw_devices.io",
-- load device file with GPIO input device, this must be specific to the platform
"rom/gpio_input.io",
-- load generic vbus file which attaches the input device to a virtual bus
"rom/gpio_input.vbus");
loader:start(
{
caps = {
vbus = input_vbus;
},
log = {"GPIO_btn", "green"}
},
"rom/ex_gpio_input");

View File

@@ -0,0 +1,13 @@
-- vi:ft=lua
local hw_bus = Io.system_bus()
-- add virtual busses to io
Io.add_vbusses
{
-- create a new vbus called 'gpio_input_bus'
gpio_input_bus = Io.Vi.System_bus(function()
-- connect the device which matches to 'gpio-input,btn'
irq = wrap(hw_bus:match("gpio-input,btn"));
end);
}

View File

@@ -0,0 +1,33 @@
-- vi:ft=lua
local L4 = require "L4";
loader = L4.default_loader
local led_vbus = loader:new_channel();
loader:startv(
{
caps = {
icu = L4.Env.icu;
led_bus = led_vbus:svr();
sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0);
},
log = {"io", "red"}
},
"rom/io",
-- load base device file with the SoC's hardware devices
"rom/hw_devices.io",
-- load device file with LED device, this must be specific to the platform
"rom/gpio_led.io",
-- load generic vbus file which attaches the LED device to a virtual bus
"rom/gpio_led.vbus");
loader:start(
{
caps = {
vbus = led_vbus;
},
log = {"LED", "green"}
},
"rom/ex_gpio_led");

View File

@@ -0,0 +1,14 @@
-- vi:ft=lua
local hw_bus = Io.system_bus()
-- add virtual busses to io
Io.add_vbusses
{
-- create a new virtual bus 'led_bus'
led_bus = Io.Vi.System_bus(function()
-- connect the hardware device which matches 'gpio-led'
-- to the vbus
led = wrap(hw_bus:match("gpio-led"));
end);
}

View File

@@ -0,0 +1,50 @@
-- vi:ft=lua
package.path = "rom/?.lua";
local L4 = require "L4";
local l = L4.default_loader
l.default_caps = { rom = L4.Env.rom, jdb = L4.Env.jdb }
local log_fab = l:new_channel();
l.log_fab = log_fab
function new_sched(prio, cpus)
return L4.Env.user_factory:create(L4.Proto.Scheduler, prio + 10, prio, cpus);
end
-- Start cons
l:start(
{
scheduler = new_sched(14, 0x01), -- runs only on CPU0
log = L4.Env.log,
caps = { cons = log_fab:svr() }
}, "rom/cons -a");
-- Create ipc gate for vbus and start io
local rpi_vbus = l:new_channel();
l:startv(
{
scheduler = new_sched(0, 0x02), -- runs only on CPU1
caps =
{
icu = L4.Env.icu,
rpi_vbus = rpi_vbus:svr(),
sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0),
},
log = { "io", "cyan" },
}, "rom/io",
"rom/hw_devices.io",
"rom/gpio_uart.io",
"rom/gpio_uart.vbus")
-- Start the demo app
l:start(
{
scheduler = new_sched(0, 0x03), -- runs only on CPU2
caps =
{
vbus = rpi_vbus,
},
}, "rom/rpi_uart");

View File

@@ -0,0 +1,11 @@
-- vi:ft=lua
local hw = Io.system_bus()
Io.add_vbusses
{
rpi_vbus = Io.Vi.System_bus(function()
-- Add UART4 to the virtual bus
uart4 = wrap(hw.uart4)
end);
}

View File

@@ -0,0 +1,22 @@
-- vi:ft=lua
local Hw = Io.Hw
local hw_bus = Io.system_bus()
-- add devices to io's device tree
Io.hw_add_devices(function()
-- create a new hardware device
S1_btn = Hw.Device(function()
-- Set the 'compatible' IDs for the device
compatible = {"gpio-input,btn","gpio-key"};
-- Set the 'hid' property of the device
Property.hid = "gpio-key,S1";
-- Add a GPIO pin as a resource to the device
-- on Beagleboard this is the S1 user button
Resource.key = Io.Gpio_resource(hw_bus.GPIO.GPIO1, 7, 7);
end);
end)

View File

@@ -0,0 +1,21 @@
-- vi:ft=lua
local Hw = Io.Hw
local hw_bus = Io.system_bus()
-- add devices to io's device tree
Io.Dt.add_children(hw_bus, function()
-- create a new hardware device
LED = Hw.Device(function()
-- Set the 'compatible' IDs for the device
compatible = {"gpio-led,green", "gpio-led",};
-- set 'hid' property
Property.hid = "gpio-led,D7";
-- Add a GPIO pin as 'gled' resource to the device
-- on Beagleboard this is the green user LED D7
Resource.led = Io.Gpio_resource(hw_bus.GPIO.GPIO5, 21, 21);
end);
end)

View File

@@ -0,0 +1,21 @@
-- vi:ft=lua
local Hw = Io.Hw
local hw_bus = Io.system_bus()
-- add devices to io's device tree
Io.hw_add_devices(function()
-- create a new hardware device
S4_btn = Hw.Device(function()
-- Set the 'compatible' IDs for this device
compatible = {"gpio-input,btn","gpio-key"};
-- Set the 'hid' property of the device
Property.hid = "gpio-key,S4";
-- Add a GPIO pin as resource 'btn0' to the device
-- on Omap5uevm this is the S4 push button
Resource.key = Io.Gpio_resource(hw_bus.GPIO.GPIO3, 19, 19);
end);
end)

View File

@@ -0,0 +1,21 @@
-- vi:ft=lua
local Hw = Io.Hw
local hw_bus = Io.system_bus()
-- add devices to io's device tree
Io.Dt.add_children(hw_bus, function()
-- create a LED device
LED = Hw.Device(function()
-- Set the 'compatible' IDs for this device
compatible = {"gpio-led,blue", "gpio-led",};
-- set 'hid' property
Property.hid = "gpio-led,D1";
-- Add a GPIO pin as 'bled' resource to the device
-- on OMAP5432uevm this is the blue user LED D1
Resource.led = Io.Gpio_resource(hw_bus.GPIO.GPIO5, 25, 25);
end);
end)

View File

@@ -0,0 +1,21 @@
-- vi:ft=lua
local Hw = Io.Hw
local hw_bus = Io.system_bus()
-- add devices to io's device tree
Io.hw_add_devices(function()
-- create a new hardware device
S2_btn = Hw.Device(function()
-- Set the 'compatible' IDs for the device
compatible = {"gpio-input,btn","gpio-key"};
-- Set the 'hid' property of the device
Property.hid = "gpio-key,S2";
-- Add a GPIO pin as a resource to the device
-- on Pandaboard this is the S2 push button
Resource.key = Io.Gpio_resource(hw_bus.GPIO.GPIO4, 25, 25);
end);
end)

View File

@@ -0,0 +1,23 @@
-- vi:ft=lua
local Hw = Io.Hw
local hw_bus = Io.system_bus()
-- add devices to io's device tree
Io.Dt.add_children(hw_bus, function()
-- create a new hardware device
LED = Hw.Device(function()
-- Set the 'compatible' IDs for the device
compatible = {"gpio-led,green", "gpio-led",};
-- set 'hid' property
Property.hid = "gpio-led,D1";
-- Add a GPIO pin as 'gled' resource to the device
-- on Pandaboard this is the green status LED D1
Resource.led = Io.Gpio_resource(hw_bus.GPIO.GPIO1, 7, 7);
-- connect LED to pin 6 of connector J3
--Resource.wled = Io.Gpio_resource(hw_bus.GPIO.GPIO5, 28, 28);
end);
end)

View File

@@ -0,0 +1,21 @@
-- vi:ft=lua
local Hw = Io.Hw
local hw_bus = Io.system_bus()
-- add devices to io's device tree
Io.hw_add_devices(function()
-- create a new hardware device
BTN = Hw.Device(function()
-- Set the 'compatible' IDs for the device
compatible = {"gpio-input,btn","gpio-key"};
-- Set the 'hid' property of the device
Property.hid = "gpio-key,User"
-- Add a GPIO pin as a resource to the device
Resource.key = Io.Gpio_resource(hw_bus.GPIO, 22, 22);
end);
end)

View File

@@ -0,0 +1,22 @@
-- vi:ft=lua
local Hw = Io.Hw
local hw_bus = Io.system_bus()
-- add devices to io's device tree
Io.hw_add_devices(function()
-- create a new hardware device
ACT_LED = Hw.Device(function()
-- Set the 'compatible' IDs for the device
compatible = {"gpio-led,green", "gpio-led",};
-- set 'hid' property
Property.hid = "gpio-led,ACT";
-- Add a GPIO pin as 'led' resource to the device
-- ACT LED on Raspberry Pi: original B - Pi 3: GPIO pin 16
-- Pi 4: GPIO pin 42
Resource.led = Io.Gpio_resource(hw_bus.GPIO, 42, 42);
end);
end)

View File

@@ -0,0 +1,14 @@
-- vi:ft=lua
local hw = Io.system_bus()
Io.hw_add_devices(function()
-- UART4 HW device
uart4 = Io.Hw.Device(function()
compatible = {"arm,pl011","arm,primecell"};
Property.hid = "Raspberry Pi 4 UART4";
Resource.reg0 = Io.Res.mmio(0xfe201800 , 0xfe201800 + 0x200 - 1);
Resource.irq0 = Io.Res.irq(32 + 121, Io.Resource.Irq_type_level_high);
Resource.io0 = Io.Gpio_resource(hw.GPIO, 8, 9);
end);
end)

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_gpio_input
SRC_CC = gpio_input.cc
REQUIRES_LIBS = libstdc++ libio-vbus
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,147 @@
/* SPDX-License-Identifier: MIT */
/*
* (c) 2014 Matthias Lange <matthias.lange@kernkonzept.com>
*/
#include <iostream>
#include <unistd.h>
#include <l4/re/env>
#include <l4/re/error_helper>
#include <l4/re/util/cap_alloc>
#include <l4/re/util/unique_cap>
#include <l4/re/util/object_registry>
#include <l4/re/util/br_manager>
#include <l4/vbus/vbus_gpio>
#include <l4/vbus/vbus>
#include <l4/sys/cxx/ipc_epiface>
#include <l4/cxx/exceptions>
#include <l4/cxx/unique_ptr>
using namespace std;
static L4Re::Util::Registry_server<> server;
class Gpio_input_server : public L4::Irqep_t<Gpio_input_server>
{
L4::Cap<L4::Icu> _icu;
int _irq_num;
public:
Gpio_input_server(L4::Cap<L4::Icu> icu, int irq) : _icu(icu), _irq_num(irq) { }
void handle_irq()
{
cout << "Received IRQ" << endl;
// ready to receive next Irq
_icu->unmask(_irq_num);
}
};
int main()
{
cout << "Hello, this is ex_gpio_input" << endl;
try
{
L4::Cap<L4vbus::Vbus> vbus =
L4Re::chkcap(L4Re::Env::env()->get_cap<L4vbus::Vbus>("vbus"),
"Could not find 'vbus' capability.\n"
"Check your lua config");
L4vbus::Device root(vbus, L4VBUS_ROOT_BUS);
L4vbus::Device dev;
L4vbus::Icu icu_dev;
unsigned pin = ~0;
l4vbus_device_handle_t gpio_handle = ~0;
// find ICU
L4Re::chksys(root.device_by_hid(&dev, "L40009"));
icu_dev = static_cast<L4vbus::Icu &>(dev);
l4vbus_device_t dev_info;
while (root.next_device(&dev, L4VBUS_MAX_DEPTH, &dev_info) == 0)
{
// match device against 'gpio-key' compatibility ID
if (dev.is_compatible("gpio-key") == 1)
{
// get device resources, e.g. GPIO pin number
// this is needed to create the GPIO pin device later
for (unsigned i = 0; i < dev_info.num_resources; ++i)
{
l4vbus_resource_t res;
if (dev.get_resource(i, &res))
break;
if (res.type == L4VBUS_RESOURCE_GPIO)
{
gpio_handle = res.provider;
pin = res.start;
}
}
// we found the device, exit
break;
}
}
if (gpio_handle == ~0)
throw L4::Runtime_error(-L4_ENODEV, "No button found.");
L4vbus::Device gpio_dev(vbus, gpio_handle);
L4vbus::Gpio_pin irq_pin(gpio_dev, pin);
// configure pin as Input
L4Re::chksys(irq_pin.setup(L4VBUS_GPIO_SETUP_INPUT, 0),
"Failed to configure GPIO pin.");
// get the IRQ number for this pin
int _irq_num;
L4Re::chksys(_irq_num = irq_pin.to_irq(), "Failed to aquire Irq.");
// set pud mode
L4Re::chksys(irq_pin.config_pull(L4VBUS_GPIO_PIN_PULL_DOWN),
"Failed to configure PULL mode.");
// allocate capability slot for the Icu
L4Re::Util::Unique_cap<L4::Icu> _icu =
L4Re::chkcap(L4Re::Util::make_unique_cap<L4::Icu>(),
"Could not allocate icu cap.");
// retrieve Icu capability
L4Re::chksys(icu_dev.vicu(_icu.get()),
"Could not retrieve icu cap.");
enum Irq_mode : unsigned { Mode = L4_IRQ_F_BOTH_EDGE, };
// 1. set irq mode
L4Re::chksys(_icu->set_mode(_irq_num, Mode),
"Could not set Irq mode.");
// 2. register server object
cxx::unique_ptr<Gpio_input_server> gpio_irq =
cxx::make_unique<Gpio_input_server>(_icu.get(), _irq_num);
L4::Cap<L4::Irq> _irq = server.registry()->register_irq_obj(gpio_irq.get());
// 3. bind irq cap with irq number to Icu
L4Re::chksys(_icu->bind(_irq_num, _irq),
"Could not bind Irq capability.");
// 4. unmask irq
// unmask() is a sender-only IPC, the return value is undefined
// that's why we don't need to check it using chksys
_icu->unmask(_irq_num);
gpio_irq.release();
server.loop();
}
catch (L4::Runtime_error &e)
{
cerr << "Runtime error: " << e.str() << ". Reason: " << e.extra_str()
<< endl;
}
return 0;
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_gpio_led
SRC_CC = gpio_led.cc
REQUIRES_LIBS = libstdc++ libio-vbus
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,134 @@
/* SPDX-License-Identifier: MIT */
/*
* (c) 2014 Maksym Planeta <mcsim.planeta@gmail.com>
* Matthias Lange <matthias.lange@kernkonzept.com>
*/
#include <iostream>
#include <unistd.h>
#include <l4/re/env>
#include <l4/re/error_helper>
#include <l4/vbus/vbus_gpio>
#include <l4/vbus/vbus>
#include <l4/cxx/exceptions>
#include <l4/cxx/ipc_timeout_queue>
#include <l4/re/util/object_registry>
#include <l4/cxx/unique_ptr>
using namespace std;
class My_loop_hooks :
public L4::Ipc_svr::Timeout_queue_hooks<My_loop_hooks>,
public L4::Ipc_svr::Ignore_errors
{
public:
/**
* method required for Timeout_queue
*/
l4_kernel_clock_t now() { return l4_kip_clock(l4re_kip()); }
};
/**
* This class implements the periodic state change of the LED
*/
class Blinking_led : public L4::Ipc_svr::Timeout_queue::Timeout
{
public:
/**
* interval has to be in microseconds
*/
Blinking_led(L4::Ipc_svr::Server_iface *sif, L4vbus::Gpio_pin *led,
unsigned interval)
: _sif(sif), _led(led), _interval(interval)
{
// add ourselves to the server's timeout queue
// absolute timeout with _interval length
_sif->add_timeout(this, l4_kip_clock(l4re_kip()) + _interval);
}
/**
* This function gets called when the timeout has expired
*/
void expired()
{
unsigned v = _led->get();
_led->set(~v & 0x1);
_sif->add_timeout(this, timeout() + _interval);
}
private:
L4::Ipc_svr::Server_iface *_sif;
L4vbus::Gpio_pin *_led;
unsigned _interval;
};
L4Re::Util::Registry_server<My_loop_hooks> server;
int main()
{
cout << "Hello, this is ex_gpio_led" << endl;
try
{
L4::Cap<L4vbus::Vbus> vbus =
L4Re::chkcap(L4Re::Env::env()->get_cap<L4vbus::Vbus>("vbus"),
"Could not find 'vbus' capability.\nCheck your lua config");
L4vbus::Device root(vbus, L4VBUS_ROOT_BUS);
L4vbus::Device dev;
unsigned pin = ~0;
l4vbus_device_handle_t gpio_handle = ~0;
l4vbus_device_t dev_info;
while (root.next_device(&dev, L4VBUS_MAX_DEPTH, &dev_info) == 0)
{
// find LED which is connected via GPIO
if (dev.is_compatible("gpio-led") == 1)
{
// get device resources, e.g. GPIO pin number
// this is needed to create the GPIO pin device later
for (unsigned i = 0; i < dev_info.num_resources; ++i)
{
l4vbus_resource_t res;
if (dev.get_resource(i, &res))
break;
if (res.type == L4VBUS_RESOURCE_GPIO)
{
pin = res.start;
gpio_handle = res.provider;
}
}
// we found a matching device, exit
break;
}
}
if (gpio_handle == ~0)
throw L4::Runtime_error(-L4_ENODEV, "No compatible LED device found.");
L4vbus::Device gpio_dev(vbus, gpio_handle);
cxx::unique_ptr<L4vbus::Gpio_pin> led =
cxx::make_unique<L4vbus::Gpio_pin>(gpio_dev, pin);
// configure pin as Output
L4Re::chksys(led->setup(L4VBUS_GPIO_SETUP_OUTPUT, 0),
"Failed to setup GPIO pin.");
// 500ms interval
Blinking_led b(&server, led.get(), 500000);
led.release();
server.loop();
}
catch (L4::Runtime_error &e)
{
cerr << "Runtime error: " << e.str() << ". Reason: " << e.extra_str()
<< endl;
}
return 0;
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
REQUIRES_LIBS = libstdc++ libio-vbus drivers_uart libio
TARGET = rpi_uart
SRC_CC = main.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,255 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright (C) 2022, 2024 Kernkonzept GmbH.
* Author(s): Christian Pötzsch <christian.poetzsch@kernkonzept.com>
*
*/
#include <iostream>
#include <unistd.h>
#include <memory>
#include <cstring>
#include <cstdio>
#include <l4/vbus/vbus>
#include <l4/vbus/vbus_gpio>
#include <l4/re/env>
#include <l4/re/error_helper>
#include <l4/re/util/cap_alloc>
#include <l4/re/util/unique_cap>
#include <l4/re/util/object_registry>
#include <l4/re/util/br_manager>
#include <l4/re/util/debug>
#include <terminate_handler-l4>
#include <l4/sys/cxx/ipc_epiface>
#include <l4/cxx/exceptions>
#include <l4/cxx/unique_ptr>
#include "l4/drivers/uart_pl011.h"
/*
* This example shows how to use uart4 of an Raspberry 4.
*
* This uart uses pin 8 (tx) and 9 (rx) when the gpio block for those pins is
* set to alternate mode 4.
*
* Therefor we query the gpio device from io and reprogram the gpio block for
* those two pins.
*
* Afterwards we can initialize the uart device with the given io memory
* location. The required pl011 uart driver is in the drivers-frst package.
*
* To test this setup, two serial to usb converters are required. Connect pin
* 14/15/ground for the console uart and pin 8/9/ground for the extra uart.
*
* This example will print on both consoles different strings in a loop.
*
*/
//using namespace std;
// Create registry
static L4Re::Util::Registry_server<L4Re::Util::Br_manager_hooks> server;
class Serial_drv : public L4::Irqep_t<Serial_drv>
{
L4::Cap<L4::Icu> _icu;
L4::Cap<L4::Irq> _irq;
public:
Serial_drv(L4::Cap<L4::Icu> icu, l4_addr_t regs) :
_icu(icu)
{
_regs = std::make_shared<L4::Io_register_block_mmio>(regs);
_uart = std::make_shared<L4::Uart_pl011>(48000001);
_uart->startup(_regs.get());
_uart->enable_rx_irq(true);
}
void init(L4::Cap<L4::Irq> irq) { _irq = irq; }
void write(const char *s)
{
auto l = strlen(s);
_uart->write(s, l);
}
std::string read()
{
std::string s;
for (;;)
{
auto c =_uart->get_char(true);
if (c == '\r')
{
const char *n = "\r\n";
_uart->write(n, 2);
break;
}
else
{
_uart->write((const char*)&c, 1);
s += (char)c;
}
}
return s;
}
int handle_irq()
{
auto c =_uart->get_char(true);
if (c == '\r')
{
const char *n = "\r\n";
_uart->write(n, 2);
}
else
{
_uart->write((const char*)&c, 1);
}
_irq->unmask();
return 0;
}
private:
std::shared_ptr<L4::Io_register_block_mmio> _regs;
std::shared_ptr<L4::Uart> _uart;
L4::Cap<L4::Icu> _dev_icu;
L4::Cap<L4::Irq_eoi> _eoi;
};
int main(void)
{
std::cout << "Hello, this is ex_gpio_uart" << std::endl;
try
{
L4::Cap<L4vbus::Vbus> vbus =
L4Re::chkcap(L4Re::Env::env()->get_cap<L4vbus::Vbus>("vbus"),
"Get vbus capability.", -L4_ENOENT);
L4vbus::Device root(vbus, L4VBUS_ROOT_BUS);
L4vbus::Device dev;
L4vbus::Icu icu_dev;
// find ICU
L4Re::chksys(root.device_by_hid(&dev, "L40009"),
"Request ICU device from vbus");
icu_dev = static_cast<L4vbus::Icu &>(dev);
l4vbus_device_t dev_info;
bool gpio_init = false;
l4_addr_t uart_addr = 0;
l4_size_t uart_size = 0;
int uart_irq = 0;
// Scan vbus for hw devices
while (root.next_device(&dev, L4VBUS_MAX_DEPTH, &dev_info) == L4_EOK)
{
// match device against 'arm,pl011' compatibility ID
if (dev.is_compatible("arm,pl011") == 1)
{
// get all device resources: MMIO, IRQ, GPIO pins for TX and RX
for (unsigned i = 0; i < dev_info.num_resources; ++i)
{
l4vbus_resource_t res;
if (dev.get_resource(i, &res))
break;
if (res.type == L4VBUS_RESOURCE_MEM)
{
uart_addr = res.start;
uart_size = res.end - res.start + 1;
}
if (res.type == L4VBUS_RESOURCE_IRQ)
uart_irq = res.start;
if (res.type == L4VBUS_RESOURCE_GPIO)
{
gpio_init = true;
L4vbus::Gpio_module chipdev = L4vbus::Device(vbus, res.provider);
L4vbus::Gpio_module::Pin_slice
pin_slice(0, 1<<res.start | 1<<res.end);
chipdev.setup(pin_slice, 3, 0);
chipdev.pin(res.start).config_pull(0x100); // Pull_none
chipdev.pin(res.end).config_pull(0x200); // Pull_up
}
}
}
}
if (!gpio_init)
L4Re::throw_error(-L4_EINVAL, "Gpio wasn't found\n");
if (!uart_addr)
L4Re::throw_error(-L4_EINVAL, "Uart has no MMIO resource.\n");
if (!uart_irq)
L4Re::throw_error(-L4_EINVAL, "Uart has no IRQ resource.\n");
// map MMIO memory
l4_addr_t offs = uart_addr - l4_trunc_page(uart_addr);
L4::Cap<L4Re::Dataspace> iocap =
L4::cap_reinterpret_cast<L4Re::Dataspace>(root.bus_cap());
l4_addr_t uart_vaddr = 0;
l4_addr_t addr_trunc = l4_trunc_page(uart_addr);
L4Re::chksys(L4Re::Env::env()->rm()->attach(&uart_vaddr, uart_size + offs,
L4Re::Rm::F::Search_addr
| L4Re::Rm::F::Cache_uncached
| L4Re::Rm::F::RW,
L4::Ipc::make_cap_rw(iocap),
addr_trunc, L4_PAGESHIFT));
printf("Device MMIO mapped @ %lx:%zx\n", uart_vaddr, uart_size);
// allocate capability slot for the Icu
L4Re::Util::Unique_cap<L4::Icu> _icu =
L4Re::chkcap(L4Re::Util::make_unique_cap<L4::Icu>(), "Allocate icu cap.");
// retrieve Icu capability
L4Re::chksys(icu_dev.vicu(_icu.get()), "Request ICU cap from vbus");
// 1. set irq mode
L4Re::chksys(_icu->set_mode(uart_irq, L4_IRQ_F_LEVEL_HIGH));
// 2. create and register server object
cxx::unique_ptr<Serial_drv> drv =
cxx::make_unique<Serial_drv>(_icu.get(), uart_vaddr + offs);
L4::Cap<L4::Irq> _irq = server.registry()->register_irq_obj(drv.get());
// 3. bind irq cap with irq number to Icu
l4_msgtag_t ret;
L4Re::chksys(ret = _icu->bind(uart_irq, _irq),
"Binding Irq capability to Icu");
drv.get()->init(_irq);
// 4. unmask irq
_irq->unmask();
printf("Console UART\n");
drv.get()->write("Secondary UART\r\n");
drv.release();
// Start server loop
server.loop();
}
catch (L4::Runtime_error &e)
{
std::cerr << "Runtime error: " << e.str() << ". Reason: " << e.extra_str()
<< std::endl;
}
return 0;
}

View File

@@ -0,0 +1,57 @@
requires: stdlibs
# boost, cppunit, stdthread
optional: libstdc++
# boost
optional: libsupc++ libboost atkins
# cairo, l4re, libpng, Mesa, readline, slab
optional: l4re_c-util
# cppunit
optional: libcppunit
# httpfs
optional: libl4revfs-fs-httpfs ankh liblwip_netif_ankh
# inputtst
optional: input
# l4util, slab
optional: l4util
# l4util
optional: libsigma0
# libc_thread_safe, pthread, shmc, stdthread, suspend
optional: libpthread
# libgomp, libjpeg
optional: libc_support_misc
# libio, libirq
optional: libio libirq
# libjpeg
optional: libjpeg mag-gfx scout-gfx
# libpng
optional: libl4png_wrap
# Mesa
optional: Mesa libc_be_math libdl
# ncurses
optional: libncurses libc_be_sig libmount libl4revfs-fs-tarfs
# pthread, slab
optional: log
# readline
optional: dope readline libc_be_fs_noop
# own lib (dependency = name)
optional: cairo libbacktrace libgomp rtc shmc slab sqlite libtlsf
Maintainer: adam@os.inf.tu-dresden.de

View File

@@ -0,0 +1,6 @@
PKGDIR = .
L4DIR ?= $(PKGDIR)/../../..
TARGET = $(wildcard [a-zA-Z]*)
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ../
L4DIR ?= $(PKGDIR)/../../..
TARGET = inputtst
SRC_C = main.c
DEPENDS_PKGS = input
REQUIRES_LIBS = input
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,381 @@
/*****************************************************************************/
/**
* \file input/examples/inputtst/main.c
* \brief Test modes of L4INPUT
*
* \date 11/20/2003
* \author Christian Helmuth <ch12@os.inf.tu-dresden.de>
* \author Frank Mehnert <fm3@os.inf.tu-dresden.de>
*
*/
/*
* (c) 2003-2009 Author(s)
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
/* L4 */
#include <l4/util/util.h>
/* C */
#include <stdio.h>
#include <string.h>
/* input */
#include <l4/input/libinput.h>
l4_ssize_t l4libc_heapsize = 128 * 1024;
/*****************************************************************************/
char *events[EV_MAX + 1] = {
[EV_SYN] = "Sync", [EV_KEY] = "Key",
[EV_REL] = "Relative", [EV_ABS] = "Absolute",
[EV_MSC] = "Misc", [EV_SW] = "Switch",
[EV_LED] = "LED", [EV_SND] = "Sound",
[EV_REP] = "Repeat", [EV_FF] = "ForceFeedback",
[EV_PWR] = "Power", [EV_FF_STATUS] = "ForceFeedbackStatus",
};
char *keys[KEY_MAX + 1] = {
[KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc",
[KEY_1] = "1", [KEY_2] = "2",
[KEY_3] = "3", [KEY_4] = "4",
[KEY_5] = "5", [KEY_6] = "6",
[KEY_7] = "7", [KEY_8] = "8",
[KEY_9] = "9", [KEY_0] = "0",
[KEY_MINUS] = "Minus", [KEY_EQUAL] = "Equal",
[KEY_BACKSPACE] = "Backspace", [KEY_TAB] = "Tab",
[KEY_Q] = "Q", [KEY_W] = "W",
[KEY_E] = "E", [KEY_R] = "R",
[KEY_T] = "T", [KEY_Y] = "Y",
[KEY_U] = "U", [KEY_I] = "I",
[KEY_O] = "O", [KEY_P] = "P",
[KEY_LEFTBRACE] = "LeftBrace", [KEY_RIGHTBRACE] = "RightBrace",
[KEY_ENTER] = "Enter", [KEY_LEFTCTRL] = "LeftControl",
[KEY_A] = "A", [KEY_S] = "S",
[KEY_D] = "D", [KEY_F] = "F",
[KEY_G] = "G", [KEY_H] = "H",
[KEY_J] = "J", [KEY_K] = "K",
[KEY_L] = "L", [KEY_SEMICOLON] = "Semicolon",
[KEY_APOSTROPHE] = "Apostrophe", [KEY_GRAVE] = "Grave",
[KEY_LEFTSHIFT] = "LeftShift", [KEY_BACKSLASH] = "BackSlash",
[KEY_Z] = "Z", [KEY_X] = "X",
[KEY_C] = "C", [KEY_V] = "V",
[KEY_B] = "B", [KEY_N] = "N",
[KEY_M] = "M", [KEY_COMMA] = "Comma",
[KEY_DOT] = "Dot", [KEY_SLASH] = "Slash",
[KEY_RIGHTSHIFT] = "RightShift", [KEY_KPASTERISK] = "KPAsterisk",
[KEY_LEFTALT] = "LeftAlt", [KEY_SPACE] = "Space",
[KEY_CAPSLOCK] = "CapsLock", [KEY_F1] = "F1",
[KEY_F2] = "F2", [KEY_F3] = "F3",
[KEY_F4] = "F4", [KEY_F5] = "F5",
[KEY_F6] = "F6", [KEY_F7] = "F7",
[KEY_F8] = "F8", [KEY_F9] = "F9",
[KEY_F10] = "F10", [KEY_NUMLOCK] = "NumLock",
[KEY_SCROLLLOCK] = "ScrollLock", [KEY_KP7] = "KP7",
[KEY_KP8] = "KP8", [KEY_KP9] = "KP9",
[KEY_KPMINUS] = "KPMinus", [KEY_KP4] = "KP4",
[KEY_KP5] = "KP5", [KEY_KP6] = "KP6",
[KEY_KPPLUS] = "KPPlus", [KEY_KP1] = "KP1",
[KEY_KP2] = "KP2", [KEY_KP3] = "KP3",
[KEY_KP0] = "KP0", [KEY_KPDOT] = "KPDot",
[KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd",
[KEY_F11] = "F11", [KEY_F12] = "F12",
[KEY_RO] = "RO", [KEY_KATAKANA] = "Katakana",
[KEY_HIRAGANA] = "HIRAGANA", [KEY_HENKAN] = "Henkan",
[KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] = "Muhenkan",
[KEY_KPJPCOMMA] = "KPJpComma", [KEY_KPENTER] = "KPEnter",
[KEY_RIGHTCTRL] = "RightCtrl", [KEY_KPSLASH] = "KPSlash",
[KEY_SYSRQ] = "SysRq", [KEY_RIGHTALT] = "RightAlt",
[KEY_LINEFEED] = "LineFeed", [KEY_HOME] = "Home",
[KEY_UP] = "Up", [KEY_PAGEUP] = "PageUp",
[KEY_LEFT] = "Left", [KEY_RIGHT] = "Right",
[KEY_END] = "End", [KEY_DOWN] = "Down",
[KEY_PAGEDOWN] = "PageDown", [KEY_INSERT] = "Insert",
[KEY_DELETE] = "Delete", [KEY_MACRO] = "Macro",
[KEY_MUTE] = "Mute", [KEY_VOLUMEDOWN] = "VolumeDown",
[KEY_VOLUMEUP] = "VolumeUp", [KEY_POWER] = "Power",
[KEY_KPEQUAL] = "KPEqual", [KEY_KPPLUSMINUS] = "KPPlusMinus",
[KEY_PAUSE] = "Pause", [KEY_KPCOMMA] = "KPComma",
[KEY_HANGUEL] = "Hanguel", [KEY_HANJA] = "Hanja",
[KEY_YEN] = "Yen", [KEY_LEFTMETA] = "LeftMeta",
[KEY_RIGHTMETA] = "RightMeta", [KEY_COMPOSE] = "Compose",
[KEY_STOP] = "Stop", [KEY_AGAIN] = "Again",
[KEY_PROPS] = "Props", [KEY_UNDO] = "Undo",
[KEY_FRONT] = "Front", [KEY_COPY] = "Copy",
[KEY_OPEN] = "Open", [KEY_PASTE] = "Paste",
[KEY_FIND] = "Find", [KEY_CUT] = "Cut",
[KEY_HELP] = "Help", [KEY_MENU] = "Menu",
[KEY_CALC] = "Calc", [KEY_SETUP] = "Setup",
[KEY_SLEEP] = "Sleep", [KEY_WAKEUP] = "WakeUp",
[KEY_FILE] = "File", [KEY_SENDFILE] = "SendFile",
[KEY_DELETEFILE] = "DeleteFile", [KEY_XFER] = "X-fer",
[KEY_PROG1] = "Prog1", [KEY_PROG2] = "Prog2",
[KEY_WWW] = "WWW", [KEY_MSDOS] = "MSDOS",
[KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction",
[KEY_CYCLEWINDOWS] = "CycleWindows", [KEY_MAIL] = "Mail",
[KEY_BOOKMARKS] = "Bookmarks", [KEY_COMPUTER] = "Computer",
[KEY_BACK] = "Back", [KEY_FORWARD] = "Forward",
[KEY_CLOSECD] = "CloseCD", [KEY_EJECTCD] = "EjectCD",
[KEY_EJECTCLOSECD] = "EjectCloseCD", [KEY_NEXTSONG] = "NextSong",
[KEY_PLAYPAUSE] = "PlayPause", [KEY_PREVIOUSSONG] = "PreviousSong",
[KEY_STOPCD] = "StopCD", [KEY_RECORD] = "Record",
[KEY_REWIND] = "Rewind", [KEY_PHONE] = "Phone",
[KEY_ISO] = "ISOKey", [KEY_CONFIG] = "Config",
[KEY_HOMEPAGE] = "HomePage", [KEY_REFRESH] = "Refresh",
[KEY_EXIT] = "Exit", [KEY_MOVE] = "Move",
[KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp",
[KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] = "KPLeftParenthesis",
[KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "KEY_NEW",
[KEY_REDO] = "KEY_REDO", [KEY_F13] = "F13",
[KEY_F14] = "F14", [KEY_F15] = "F15",
[KEY_F16] = "F16", [KEY_F17] = "F17",
[KEY_F18] = "F18", [KEY_F19] = "F19",
[KEY_F20] = "F20", [KEY_F21] = "F21",
[KEY_F22] = "F22", [KEY_F23] = "F23",
[KEY_F24] = "F24", [KEY_PLAYCD] = "PlayCD",
[KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3",
[KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend",
[KEY_CLOSE] = "Close", [KEY_PLAY] = "Play",
[KEY_FASTFORWARD] = "Fast Forward", [KEY_BASSBOOST] = "Bass Boost",
[KEY_PRINT] = "Print", [KEY_HP] = "HP",
[KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound",
[KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email",
[KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search",
[KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance",
[KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop",
[KEY_ALTERASE] = "Alternate Erase", [KEY_CANCEL] = "Cancel",
[KEY_BRIGHTNESSDOWN] = "Brightness down", [KEY_BRIGHTNESSUP] = "Brightness up",
[KEY_MEDIA] = "Media", [KEY_SWITCHVIDEOMODE] = "Switch video",
[KEY_KBDILLUMTOGGLE] = "KBDILLUMTOGGLE", [KEY_KBDILLUMDOWN] = "KBDILLUMDOWN",
[KEY_KBDILLUMUP] = "KBDILLUMUP", [KEY_SEND] = "Send",
[KEY_REPLY] = "Reply", [KEY_FORWARDMAIL] = "Forward",
[KEY_SAVE] = "Save", [KEY_DOCUMENTS] = "Documents",
[KEY_UNKNOWN] = "Unknown",
[BTN_0] = "Btn0", [BTN_1] = "Btn1",
[BTN_2] = "Btn2", [BTN_3] = "Btn3",
[BTN_4] = "Btn4", [BTN_5] = "Btn5",
[BTN_6] = "Btn6", [BTN_7] = "Btn7",
[BTN_8] = "Btn8", [BTN_9] = "Btn9",
[BTN_LEFT] = "LeftBtn", [BTN_RIGHT] = "RightBtn",
[BTN_MIDDLE] = "MiddleBtn", [BTN_SIDE] = "SideBtn",
[BTN_EXTRA] = "ExtraBtn", [BTN_FORWARD] = "ForwardBtn",
[BTN_BACK] = "BackBtn", [BTN_TASK] = "TaskBtn",
[BTN_TRIGGER] = "Trigger", [BTN_THUMB] = "ThumbBtn",
[BTN_THUMB2] = "ThumbBtn2", [BTN_TOP] = "TopBtn",
[BTN_TOP2] = "TopBtn2", [BTN_PINKIE] = "PinkieBtn",
[BTN_BASE] = "BaseBtn", [BTN_BASE2] = "BaseBtn2",
[BTN_BASE3] = "BaseBtn3", [BTN_BASE4] = "BaseBtn4",
[BTN_BASE5] = "BaseBtn5", [BTN_BASE6] = "BaseBtn6",
[BTN_DEAD] = "BtnDead", [BTN_A] = "BtnA",
[BTN_B] = "BtnB", [BTN_C] = "BtnC",
[BTN_X] = "BtnX", [BTN_Y] = "BtnY",
[BTN_Z] = "BtnZ", [BTN_TL] = "BtnTL",
[BTN_TR] = "BtnTR", [BTN_TL2] = "BtnTL2",
[BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect",
[BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode",
[BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR",
[BTN_TOOL_PEN] = "ToolPen", [BTN_TOOL_RUBBER] = "ToolRubber",
[BTN_TOOL_BRUSH] = "ToolBrush", [BTN_TOOL_PENCIL] = "ToolPencil",
[BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger",
[BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens",
[BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus",
[BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "Tool Doubletap",
[BTN_TOOL_TRIPLETAP] = "Tool Tripletap", [BTN_GEAR_DOWN] = "WheelBtn",
[BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok",
[KEY_SELECT] = "Select", [KEY_GOTO] = "Goto",
[KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2",
[KEY_OPTION] = "Option", [KEY_INFO] = "Info",
[KEY_TIME] = "Time", [KEY_VENDOR] = "Vendor",
[KEY_ARCHIVE] = "Archive", [KEY_PROGRAM] = "Program",
[KEY_CHANNEL] = "Channel", [KEY_FAVORITES] = "Favorites",
[KEY_EPG] = "EPG", [KEY_PVR] = "PVR",
[KEY_MHP] = "MHP", [KEY_LANGUAGE] = "Language",
[KEY_TITLE] = "Title", [KEY_SUBTITLE] = "Subtitle",
[KEY_ANGLE] = "Angle", [KEY_ZOOM] = "Zoom",
[KEY_MODE] = "Mode", [KEY_KEYBOARD] = "Keyboard",
[KEY_SCREEN] = "Screen", [KEY_PC] = "PC",
[KEY_TV] = "TV", [KEY_TV2] = "TV2",
[KEY_VCR] = "VCR", [KEY_VCR2] = "VCR2",
[KEY_SAT] = "Sat", [KEY_SAT2] = "Sat2",
[KEY_CD] = "CD", [KEY_TAPE] = "Tape",
[KEY_RADIO] = "Radio", [KEY_TUNER] = "Tuner",
[KEY_PLAYER] = "Player", [KEY_TEXT] = "Text",
[KEY_DVD] = "DVD", [KEY_AUX] = "Aux",
[KEY_MP3] = "MP3", [KEY_AUDIO] = "Audio",
[KEY_VIDEO] = "Video", [KEY_DIRECTORY] = "Directory",
[KEY_LIST] = "List", [KEY_MEMO] = "Memo",
[KEY_CALENDAR] = "Calendar", [KEY_RED] = "Red",
[KEY_GREEN] = "Green", [KEY_YELLOW] = "Yellow",
[KEY_BLUE] = "Blue", [KEY_CHANNELUP] = "ChannelUp",
[KEY_CHANNELDOWN] = "ChannelDown", [KEY_FIRST] = "First",
[KEY_LAST] = "Last", [KEY_AB] = "AB",
[KEY_NEXT] = "Next", [KEY_RESTART] = "Restart",
[KEY_SLOW] = "Slow", [KEY_SHUFFLE] = "Shuffle",
[KEY_BREAK] = "Break", [KEY_PREVIOUS] = "Previous",
[KEY_DIGITS] = "Digits", [KEY_TEEN] = "TEEN",
[KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "Delete EOL",
[KEY_DEL_EOS] = "Delete EOS", [KEY_INS_LINE] = "Insert line",
[KEY_DEL_LINE] = "Delete line",
[KEY_FN] = "KEY_FN", [KEY_FN_ESC] = "KEY_FN_ESC",
[KEY_FN_F1] = "KEY_FN_F1", [KEY_FN_F2] = "KEY_FN_F2",
[KEY_FN_F3] = "KEY_FN_F3", [KEY_FN_F4] = "KEY_FN_F4",
[KEY_FN_F5] = "KEY_FN_F5", [KEY_FN_F6] = "KEY_FN_F6",
[KEY_FN_F7] = "KEY_FN_F7", [KEY_FN_F8] = "KEY_FN_F8",
[KEY_FN_F9] = "KEY_FN_F9", [KEY_FN_F10] = "KEY_FN_F10",
[KEY_FN_F11] = "KEY_FN_F11", [KEY_FN_F12] = "KEY_FN_F12",
[KEY_FN_1] = "KEY_FN_1", [KEY_FN_2] = "KEY_FN_2",
[KEY_FN_D] = "KEY_FN_D", [KEY_FN_E] = "KEY_FN_E",
[KEY_FN_F] = "KEY_FN_F", [KEY_FN_S] = "KEY_FN_S",
[KEY_FN_B] = "KEY_FN_B",
};
//char *absval[5] = { "Value", "Min ", "Max ", "Fuzz ", "Flat " };
char *relatives[REL_MAX + 1] = {
[REL_X] = "X", [REL_Y] = "Y",
[REL_Z] = "Z", [REL_RX] = "RX",
[REL_RY] = "RY", [REL_RZ] = "RZ",
[REL_HWHEEL] = "HWheel", [REL_DIAL] = "Dial",
[REL_WHEEL] = "Wheel", [REL_MISC] = "Misc",
};
char *absolutes[ABS_MAX + 1] = {
[ABS_X] = "X", [ABS_Y] = "Y",
[ABS_Z] = "Z", [ABS_RX] = "Rx",
[ABS_RY] = "Ry", [ABS_RZ] = "Rz",
[ABS_THROTTLE] = "Throttle", [ABS_RUDDER] = "Rudder",
[ABS_WHEEL] = "Wheel", [ABS_GAS] = "Gas",
[ABS_BRAKE] = "Brake", [ABS_HAT0X] = "Hat0X",
[ABS_HAT0Y] = "Hat0Y", [ABS_HAT1X] = "Hat1X",
[ABS_HAT1Y] = "Hat1Y", [ABS_HAT2X] = "Hat2X",
[ABS_HAT2Y] = "Hat2Y", [ABS_HAT3X] = "Hat3X",
[ABS_HAT3Y] = "Hat 3Y", [ABS_PRESSURE] = "Pressure",
[ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt",
[ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "Tool Width",
[ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc",
};
char *misc[MSC_MAX + 1] = {
[MSC_SERIAL] = "Serial", [MSC_PULSELED] = "Pulseled",
[MSC_GESTURE] = "Gesture", [MSC_RAW] = "RawData",
[MSC_SCAN] = "ScanCode",
};
char *leds[LED_MAX + 1] = {
[LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock",
[LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose",
[LED_KANA] = "Kana", [LED_SLEEP] = "Sleep",
[LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute",
[LED_MISC] = "Misc", [LED_MAIL] = "Mail",
[LED_CHARGING] = "Charging",
};
char *repeats[REP_MAX + 1] = {
[REP_DELAY] = "Delay", [REP_PERIOD] = "Period",
};
char *sounds[SND_MAX + 1] = {
[SND_CLICK] = "Click", [SND_BELL] = "Bell",
[SND_TONE] = "Tone",
};
char **names[EV_MAX + 1] = {
[EV_SYN] = events, [EV_KEY] = keys,
[EV_REL] = relatives, [EV_ABS] = absolutes,
[EV_MSC] = misc, [EV_LED] = leds,
[EV_SND] = sounds, [EV_REP] = repeats,
};
#define BITS_PER_LONG (sizeof(long) * 8)
#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
#define OFF(x) ((x)%BITS_PER_LONG)
#define BIT(x) (1UL<<OFF(x))
#define LONG(x) ((x)/BITS_PER_LONG)
#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
/*****************************************************************************/
/** LOG L4INPUT EVENT TO SCREEN **/
static void log_event(struct l4input *ev)
{
if (!ev->type)
printf("inputtst: XXX type = 0 XXX\n");
printf("Event: type %d (%s), code %d (%s), value %d\n",
ev->type, events[ev->type] ? events[ev->type] : "?",
ev->code,
names[ev->type] ?
(names[ev->type][ev->code] ?
names[ev->type][ev->code] : "?") :
"?", ev->value);
if ((ev->type == EV_KEY) && (ev->value == 1)) {
l4input_pcspkr(800);
l4_sleep(20);
l4input_pcspkr(0);
}
}
/** CALLBACK MODE TEST **/
static L4_CV void event_cb(struct l4input *ev)
{
/* XXX seems stupid but it's historical */
log_event(ev);
}
/** BUFFER MODE TEST **/
static L4_CV void event_buf(void)
{
int rd, i;
static struct l4input ev[64];
while (1) {
l4_sleep(2);
if (!l4input_ispending())
continue;
rd = l4input_flush(ev, 64);
for (i = 0; i < rd; i++)
log_event(&ev[i]);
}
}
/*****************************************************************************/
static int usage(void)
{
printf("Usage: inputtst MODE\n");
printf("MODE is one of:\n");
printf(" -cb callback mode\n");
printf(" -buf buffer mode\n");
return 1;
}
int main(int argc, char **argv)
{
if (argc < 2)
return usage();
if (strcmp(argv[1], "-cb") == 0) {
printf("Testing L4INPUT callback mode...\n");
printf("init => %d\n",
l4input_init(17, event_cb));
l4_sleep_forever();
}
else if (strcmp(argv[1], "-buf") == 0) {
printf("Testing L4INPUT buffer mode...\n");
printf("init => %d\n",
l4input_init(17, NULL));
event_buf();
}
else
return usage();
return 0;
}

View File

@@ -0,0 +1,6 @@
PKGDIR = ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = $(wildcard [a-z]*)
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,6 @@
PKGDIR = ../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = $(wildcard [a-z]*)
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,8 @@
PKGDIR ?= ../../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_l4re_ma+rm_cc
SRC_CC = ma+rm.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,112 @@
/**
* \file
* \brief Example of coarse grained memory allocation, in C++.
*/
/*
* (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/re/mem_alloc>
#include <l4/re/rm>
#include <l4/re/env>
#include <l4/re/dataspace>
#include <l4/re/util/cap_alloc>
#include <l4/sys/err.h>
#include <cstdio>
#include <cstring>
/**
* \brief Allocate memory, given in bytes in the granularity of pages.
*
* \param size_in_bytes Size to allocate, in bytes, will be truncates to
* whole pages (L4_PAGESIZE).
* \param flags Flags to control memory allocation:
* L4Re::Mem_alloc::Continuous: Physically continuous memory
* L4Re::Mem_alloc::Pinned: Pinned memory
* L4Re::Mem_alloc::Super_pages: Use big pages
* \retval virt_addr Virtual address the memory is accessible under,
* undefined if return code != 0
*
* \return 0 on success, error code otherwise
*/
static int allocate_mem(unsigned long size_in_bytes, unsigned long flags,
void **virt_addr)
{
int r;
L4::Cap<L4Re::Dataspace> d;
/* Allocate a free capability index for our data space */
d = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
if (!d.is_valid())
return -L4_ENOMEM;
size_in_bytes = l4_trunc_page(size_in_bytes);
/* Allocate memory via a dataspace */
if ((r = L4Re::Env::env()->mem_alloc()->alloc(size_in_bytes, d, flags)))
return r;
/* Make the dataspace visible in our address space */
*virt_addr = 0;
if ((r = L4Re::Env::env()->rm()->attach(virt_addr, size_in_bytes,
L4Re::Rm::F::Search_addr | L4Re::Rm::F::RW,
L4::Ipc::make_cap_rw(d), 0,
flags & L4Re::Mem_alloc::Super_pages
? L4_SUPERPAGESHIFT : L4_PAGESHIFT)))
return r;
/* Done, virtual address is in virt_addr */
return 0;
}
/**
* \brief Free previously allocated memory.
*
* \param virt_addr Virtual address return by allocate_mem
*
* \return 0 on success, error code otherwise
*/
static int free_mem(void *virt_addr)
{
int r;
L4::Cap<L4Re::Dataspace> ds;
/* Detach memory from our address space */
if ((r = L4Re::Env::env()->rm()->detach(virt_addr, &ds)))
return r;
/* Release and return capability slot to allocator */
L4Re::Util::cap_alloc.free(ds, L4Re::Env::env()->task().cap());
/* All went ok */
return 0;
}
int main(void)
{
void *virt;
/* Allocate memory: 16k Bytes (usually) */
if (allocate_mem(4 * L4_PAGESIZE, 0, &virt))
return 1;
printf("Allocated memory.\n");
/* Do something with the memory */
memset(virt, 0x12, 4 * L4_PAGESIZE);
printf("Touched memory.\n");
/* Free memory */
if (free_mem(virt))
return 2;
printf("Freed and done. Bye.\n");
return 0;
}

View File

@@ -0,0 +1,8 @@
PKGDIR ?= ../../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_periodic_task
SRC_CC = main.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,70 @@
/**
* (c) 2014 Steffen Liebergeld <steffen.liebergeld@kernkonzept.com>
*
* This file is licensed under the terms of the GNU General Public License 2.
* See the file COPYING-GPL-2 for details.
*/
#include <l4/re/error_helper>
#include <l4/re/util/object_registry>
#include <l4/cxx/ipc_timeout_queue>
#include <cstdio>
class My_loop_hooks :
public L4::Ipc_svr::Timeout_queue_hooks<My_loop_hooks>,
public L4::Ipc_svr::Ignore_errors
{
public:
/**
* This function is required by Timeout_queue_hooks to get current time.
*/
l4_kernel_clock_t now()
{
return l4_kip_clock(l4re_kip());
}
};
L4Re::Util::Registry_server<My_loop_hooks> server;
/**
* This class implements the code that needs to be run periodically.
*/
class Periodic_task : public L4::Ipc_svr::Timeout_queue::Timeout
{
public:
Periodic_task(int iterations, L4::Ipc_svr::Server_iface *sif)
: _iterations(iterations), _sif(sif)
{
// Add this to the IPC server's Timeout_queue with an absolute timeout.
// The timeout will expire in 5 seconds from now.
_sif->add_timeout(this, l4_kip_clock(l4re_kip()) + 5000000);
}
/**
* This function is called by the Timeout_queue when its timeout expired.
*/
void expired()
{
printf("Timeout expired.\n");
if (!--_iterations)
printf("Bye bye from ex_periodic_task!\n");
else
// We add ourselves back into the Timeout_queue with a new absolute timeout
// that is 5 seconds after the previous timeout.
_sif->add_timeout(this, timeout() + 5000000);
}
private:
int _iterations;
L4::Ipc_svr::Server_iface *_sif;
};
static Periodic_task task(5, &server);
int main()
{
printf("Hello from ex_periodic_task\n");
server.loop();
}

View File

@@ -0,0 +1,7 @@
PKGDIR ?= ../../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_l4re_physmem_cc
SRC_CC = physmem.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,132 @@
/**
* \file
* \brief Example of getting memory and it physical address
*/
/*
* (c) 2020 Adam Lackorzynski <adam@l4re.org>
*
* This file is part of L4Re and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/re/mem_alloc>
#include <l4/re/rm>
#include <l4/re/env>
#include <l4/re/dataspace>
#include <l4/re/dma_space>
#include <l4/re/protocols.h>
#include <l4/re/error_helper>
#include <l4/re/util/unique_cap>
#include <l4/sys/err.h>
#include <l4/sys/factory>
#include <cstdio>
#include <cstring>
#include <cassert>
static int allocate_mem(unsigned long size_in_bytes, unsigned long flags,
unsigned long phys_align, void **virt_addr,
L4Re::Util::Unique_cap<L4Re::Dma_space> &dmaspace,
L4Re::Dma_space::Dma_addr *phys_addr)
{
int r;
L4::Cap<L4Re::Dataspace> d;
/* Allocate a free capability index for our data space */
d = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
if (!d.is_valid())
return -L4_ENOMEM;
size_in_bytes = l4_trunc_page(size_in_bytes);
flags |= L4Re::Mem_alloc::Continuous;
/* Allocate memory via a dataspace */
if ((r = L4Re::Env::env()->mem_alloc()->alloc(size_in_bytes, d,
flags, phys_align)))
return r;
/* Make the dataspace visible in our address space, uncached */
*virt_addr = 0;
if ((r = L4Re::Env::env()->rm()->attach(virt_addr, size_in_bytes,
L4Re::Rm::F::Search_addr
| L4Re::Rm::F::RW
| L4Re::Rm::F::Cache_uncached,
L4::Ipc::make_cap_rw(d), 0,
flags & L4Re::Mem_alloc::Super_pages
? L4_SUPERPAGESHIFT : L4_PAGESHIFT)))
return r;
/* The the physical memory address of the allocated memory */
if ((r = dmaspace->associate(L4::Ipc::Cap<L4::Task>(),
L4Re::Dma_space::Phys_space)))
return r;
l4_size_t ps = size_in_bytes;
if ((r = dmaspace->map(L4::Ipc::make_cap_rw(d), 0, &ps,
L4Re::Dma_space::Attributes::None,
L4Re::Dma_space::Bidirectional, phys_addr)))
return r;
// The memory is L4Re::Mem_alloc::Continuous, i.e., there is only
// one size.
assert(ps == size_in_bytes);
/* Done, virtual address is in virt_addr */
return 0;
}
static int free_mem(void *virt_addr)
{
int r;
L4::Cap<L4Re::Dataspace> ds;
/* Detach memory from our address space */
if ((r = L4Re::Env::env()->rm()->detach(virt_addr, &ds)))
return r;
/* Release and return capability slot to allocator */
L4Re::Util::cap_alloc.free(ds, L4Re::Env::env()->task().cap());
/* All went ok */
return 0;
}
int main(void)
{
L4Re::Env const *e = L4Re::Env::env();
void *virt;
auto dmaspace = L4Re::chkcap(L4Re::Util::make_unique_cap<L4Re::Dma_space>());
L4Re::Dma_space::Dma_addr phys;
int r;
if ((r = l4_error(e->user_factory()->create(dmaspace.get()))))
return r;
/* Allocate memory: 16k Bytes (usually) */
if (allocate_mem(4 * L4_PAGESIZE, // size
0, // flags
2 + L4_PAGESHIFT, // 16 KByte aligned
&virt, dmaspace, &phys))
{
printf("The memory allocation failed\n");
return 1;
}
printf("Allocated memory, virtual address: %p\n", virt);
printf("Physical / DMA address: %llx\n", phys);
/* Do something with the memory */
memset(virt, 0x12, 4 * L4_PAGESIZE);
/* Free memory */
if (free_mem(virt))
return 2;
dmaspace->disassociate();
printf("Freed and done. Bye.\n");
return 0;
}

View File

@@ -0,0 +1,8 @@
PKGDIR ?= ../../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_l4re_ds_clnt ex_l4re_ds_srv
SRC_CC_ex_l4re_ds_clnt = ds_clnt.cc
SRC_CC_ex_l4re_ds_srv = ds_srv.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,110 @@
/*
* (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/re/util/cap_alloc> // L4::Cap
#include <l4/re/dataspace> // L4Re::Dataspace
#include <l4/re/rm> // L4::Rm
#include <l4/re/env> // L4::Env
#include <l4/sys/cache.h>
#include <cstring>
#include <cstdio>
#include <unistd.h>
#include "interface.h"
int main()
{
/*
* Try to get server interface cap.
*/
L4::Cap<My_interface> svr = L4Re::Env::env()->get_cap<My_interface>("shm");
if (!svr.is_valid())
{
printf("Could not get the server capability\n");
return 1;
}
/*
* Alloc data space cap slot
*/
L4::Cap<L4Re::Dataspace> ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
if (!ds.is_valid())
{
printf("Could not get capability slot!\n");
return 1;
}
/*
* Alloc server notifier IRQ cap slot
*/
L4::Cap<L4::Irq> irq = L4Re::Util::cap_alloc.alloc<L4::Irq>();
if (!irq.is_valid())
{
printf("Could not get capability slot!\n");
return 1;
}
/*
* Request shared data-space cap.
*/
if (svr->get_shared_buffer(ds, irq))
{
printf("Could not get shared memory dataspace!\n");
return 1;
}
/*
* Attach to arbitrary region
*/
char *addr = 0;
int err = L4Re::Env::env()->rm()->attach(&addr, ds->size(),
L4Re::Rm::F::Search_addr | L4Re::Rm::F::RW,
L4::Ipc::make_cap_rw(ds));
if (err < 0)
{
printf("Error attaching data space: %s\n", l4sys_errtostr(err));
return 1;
}
printf("Content: %s\n", addr);
// wait a bit for the demo effect
printf("Sleeping a bit...\n");
sleep(1);
/*
* Fill in new stuff
*/
memset(addr, 0, ds->size());
char const * const msg = "Hello from client, too!";
printf("Setting new content in shared memory\n");
snprintf(addr, strlen(msg)+1, msg);
l4_cache_clean_data((unsigned long)addr,
(unsigned long)addr + strlen(msg) + 1);
// notify the server
irq->trigger();
/*
* Detach region containing addr, result should be Detached_ds (other results
* only apply if we split regions etc.).
*/
err = L4Re::Env::env()->rm()->detach(addr, 0);
if (err)
printf("Failed to detach region\n");
/* Free objects and capabilties, just for completeness. */
L4Re::Util::cap_alloc.free(ds, L4Re::This_task);
L4Re::Util::cap_alloc.free(irq, L4Re::This_task);
return 0;
}

View File

@@ -0,0 +1,220 @@
/*
* (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/re/env>
#include <l4/re/error_helper>
#include <l4/re/namespace>
#include <l4/re/util/cap_alloc>
#include <l4/re/util/object_registry>
#include <l4/re/dataspace>
#include <l4/cxx/ipc_server>
#include <l4/util/util.h>
#include <l4/sys/typeinfo_svr>
#include <cstring>
#include <cstdio>
#include <unistd.h>
#include <pthread.h>
#include <pthread-l4.h>
#include <thread>
#include "interface.h"
/**
* A very simple server object, just providing the
* shared memory data space and an IRQ object to send a notification.
*/
class My_server_obj : public L4::Server_object_t<L4::Kobject>
{
private:
/**
* The capability to the shared memory.
*/
L4::Cap<L4Re::Dataspace> _shm;
L4::Cap<L4::Irq> _irq;
public:
/**
* Create a new object for the given data space.
*/
explicit My_server_obj(L4::Cap<L4Re::Dataspace> shm, L4::Cap<L4::Irq> irq)
: _shm(shm), _irq(irq)
{}
/**
* Dispatch function, dealing with remote requests.
*/
int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
};
int My_server_obj::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
{
// we don't care about the original object reference, however
// we could read out the access rights from the lowest 2 bits
(void) obj;
l4_msgtag_t t;
ios >> t; // extract the tag
switch (t.label())
{
case L4::Meta::Protocol:
// handle the meta protocol requests, implementing the
// runtime dynamic type system for L4 objects.
return L4::Util::handle_meta_request<My_interface>(ios);
case 0:
// since we have just one operation we have no opcode dispatch,
// and just return the data-space and the notifier IRQ capabilities
ios << _shm << _irq;
return 0;
default:
// every other protocol is not supported.
return -L4_EBADPROTO;
}
}
/**
* A simple Server object attached to a notifier IRQ.
* This provides a kind of interrupt handler integrated in our
* server.
*/
class Shm_observer : public L4::Irq_handler_object
{
private:
/**
* The pointer to the shared memory.
*/
char *_shm;
public:
/**
* Create a new object for the given shared memory.
*/
explicit Shm_observer(char *shm)
: _shm(shm)
{}
/**
* Dispatch function, dealing with remote requests.
* This is the ISR.
*/
int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
};
int Shm_observer::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
{
// We don't care about the original object reference, however
// we could read out the access rights from the lowest 2 bits
(void)obj;
// Since we end up here in this function, we got a 'message' from the IRQ
// that is bound to us. The 'ios' stream won't contain any valuable info.
(void)ios;
printf("Client sent us: %s\n", _shm);
return 0;
}
enum
{
DS_SIZE = 4 << 12,
};
static char *get_ds(L4::Cap<L4Re::Dataspace> *_ds)
{
*_ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
if (!(*_ds).is_valid())
{
printf("Dataspace allocation failed.\n");
return 0;
}
int err = L4Re::Env::env()->mem_alloc()->alloc(DS_SIZE, *_ds, 0);
if (err < 0)
{
printf("mem_alloc->alloc() failed.\n");
L4Re::Util::cap_alloc.free(*_ds);
return 0;
}
/*
* Attach DS to local address space
*/
char *_addr = 0;
err = L4Re::Env::env()->rm()->attach(&_addr, (*_ds)->size(),
L4Re::Rm::F::Search_addr | L4Re::Rm::F::RW,
L4::Ipc::make_cap_rw(*_ds));
if (err < 0)
{
printf("Error attaching data space: %s\n", l4sys_errtostr(err));
L4Re::Util::cap_alloc.free(*_ds);
return 0;
}
/*
* Success! Write something to DS.
*/
printf("Attached DS\n");
static char const * const msg = "[DS] Hello from server!";
snprintf(_addr, strlen(msg) + 1, msg);
return _addr;
}
static void *server_thread(void *)
{
L4::Cap<L4::Thread> l4_thread = Pthread::L4::cap(pthread_self());
L4Re::Util::Registry_server<> server(l4_thread, L4Re::Env::env()->factory());
L4::Cap<L4Re::Dataspace> ds;
char *addr;
if (!(addr = get_ds(&ds)))
return nullptr;
// First the IRQ handler, because we need it in the My_server_obj object
Shm_observer observer(addr);
// Registering the observer as an IRQ handler, this allocates an
// IRQ object using the factory of our server.
L4::Cap<L4::Irq> irq = server.registry()->register_irq_obj(&observer);
// Now the initial server object shared with the client via our parent.
// it provides the data-space and the IRQ capabilities to a client.
My_server_obj server_obj(ds, irq);
// Registering the server object to the capability 'shm' in our the L4Re::Env.
// This capability must be provided by the parent. (see the shared_ds.lua)
server.registry()->register_obj(&server_obj, "shm");
// Run our server loop.
server.loop();
}
int main()
{
pthread_attr_t pattr;
if (pthread_attr_init(&pattr))
L4Re::throw_error(-L4_ENOMEM, "Initialize pthread attributes");
pthread_t thr;
L4Re::chksys(pthread_create(&thr, &pattr, server_thread, nullptr),
"Create server thread");
L4Re::chksys(pthread_attr_destroy(&pattr), "Destroy pthread attributes");
l4_sleep_forever();
return 0;
}

View File

@@ -0,0 +1,42 @@
#pragma once
#include <l4/sys/capability>
#include <l4/re/dataspace>
#include <l4/cxx/ipc_stream>
/**
* Interface class for remote object.
*
* Inherits from L4::Kobject, via the L4::Kobject_t helper
* template that generates the dynamic type information for the meta
* protocol.
*/
class My_interface : public L4::Kobject_t<My_interface, L4::Kobject>
{
// Disable instantiation and copy, because we just work via
// L4::Cap<...> references.
L4_KOBJECT(My_interface)
public:
/**
* The single method of our object.
* Requesting the data space and the IRQ to notify the server.
*/
int get_shared_buffer(L4::Cap<L4Re::Dataspace> ds, L4::Cap<L4::Irq> irq) throw();
};
inline
int
My_interface::get_shared_buffer(L4::Cap<L4Re::Dataspace> ds, L4::Cap<L4::Irq> irq) throw()
{
L4::Ipc::Iostream s(l4_utcb());
// we have just a single operation, so no opcode needed
// s << Opcode;
// put receive buffer for data-space cap and the irq cap into the stream
s << L4::Ipc::Small_buf(ds)
<< L4::Ipc::Small_buf(irq);
return l4_error(s.call(cap()));
}

View File

@@ -0,0 +1,27 @@
-- Include L4 functionality
local L4 = require("L4");
-- Create a channel from the client to the server
local channel = L4.default_loader:new_channel();
-- Start the server, giving the channel with full server rights.
-- The server will have a yellow log output.
L4.default_loader:start(
{
caps = { shm = channel:svr() },
log = { "server", "yellow" }
},
"rom/ex_l4re_ds_srv"
);
-- Start the client, giving it the channel with read only rights. The
-- log output will be green.
L4.default_loader:start(
{
caps = { shm = channel },
log = { "client", "green" },
l4re_dbg = L4.Dbg.Warn
},
"rom/ex_l4re_ds_clnt"
);

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_l4re_ma+rm_c
SRC_C = ma+rm.c
REQUIRES_LIBS = l4re_c-util
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,113 @@
/**
* \file
* \brief Example of coarse grained memory allocation, in C.
*/
/*
* (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/re/c/mem_alloc.h>
#include <l4/re/c/rm.h>
#include <l4/re/c/util/cap_alloc.h>
#include <l4/sys/err.h>
#include <stdio.h>
#include <string.h>
/**
* \brief Allocate memory, given in bytes in the granularity of pages.
*
* \param size_in_bytes Size to allocate, in bytes, will be truncates to
* whole pages (L4_PAGESIZE).
* \param flags Flags to control memory allocation:
* L4RE_MA_CONTINUOUS: Physically continuous memory
* L4RE_MA_PINNED: Pinned memory
* L4RE_MA_SUPER_PAGES: Use big pages
* \retval virt_addr Virtual address the memory is accessible under,
* undefined if return code != 0
*
* \return 0 on success, error code otherwise
*/
static int allocate_mem(unsigned long size_in_bytes, unsigned long flags,
void **virt_addr)
{
int r;
l4re_ds_t ds;
/* Allocate a free capability index for our data space */
ds = l4re_util_cap_alloc();
if (l4_is_invalid_cap(ds))
return -L4_ENOMEM;
size_in_bytes = l4_trunc_page(size_in_bytes);
/* Allocate memory via a dataspace */
if ((r = l4re_ma_alloc(size_in_bytes, ds, flags)))
return r;
/* Make the dataspace visible in our address space */
*virt_addr = 0;
if ((r = l4re_rm_attach(virt_addr, size_in_bytes,
L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RWX, ds, 0,
flags & L4RE_MA_SUPER_PAGES
? L4_SUPERPAGESHIFT : L4_PAGESHIFT)))
{
/* Free dataspace again */
l4re_util_cap_free_um(ds);
return r;
}
/* Done, virtual address is in virt_addr */
return 0;
}
/**
* \brief Free previously allocated memory.
*
* \param virt_addr Virtual address return by allocate_mem
*
* \return 0 on success, error code otherwise
*/
static int free_mem(void *virt_addr)
{
int r;
l4re_ds_t ds;
/* Detach memory from our address space */
if ((r = l4re_rm_detach_ds(virt_addr, &ds)))
return r;
/* Free memory at our memory allocator */
l4re_util_cap_free_um(ds);
/* All went ok */
return 0;
}
int main(void)
{
void *virt;
/* Allocate memory: 16k Bytes (usually) */
if (allocate_mem(4 * L4_PAGESIZE, 0, &virt))
return 1;
printf("Allocated memory.\n");
/* Do something with the memory */
memset(virt, 0x12, 4 * L4_PAGESIZE);
printf("Touched memory.\n");
/* Free memory */
if (free_mem(virt))
return 2;
printf("Freed and done. Bye.\n");
return 0;
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_smap-server ex_smap-client
SRC_CC_ex_smap-server = server.cc
SRC_CC_ex_smap-client = client.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,70 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/sys/err.h>
#include <l4/sys/types.h>
#include <l4/re/env>
#include <l4/re/util/cap_alloc>
#include <l4/cxx/ipc_stream>
#include <stdio.h>
#include "shared.h"
static int
func_smap_call(L4::Cap<void> const &server)
{
L4::Ipc::Iostream s(l4_utcb());
l4_addr_t addr = 0;
int err;
if ((err = L4Re::Env::env()->rm()->reserve_area(&addr, L4_PAGESIZE,
L4Re::Rm::F::Search_addr)))
{
printf("The reservation of one page within our virtual memory failed with %d\n", err);
return 1;
}
s << L4::Opcode(Mapper::Do_map)
<< (l4_addr_t)addr;
s << L4::Ipc::Rcv_fpage::mem((l4_addr_t)addr, L4_PAGESHIFT, 0);
int r = l4_error(s.call(server.cap(), Mapper::Protocol));
if (r)
return r; // failure
printf("String sent by server: %s\n", (char *)addr);
return 0; // ok
}
int
main()
{
L4::Cap<void> server = L4Re::Env::env()->get_cap<void>("smap");
if (!server.is_valid())
{
printf("Could not get capability slot!\n");
return 1;
}
printf("Asking for page from server\n");
if (func_smap_call(server))
{
printf("Error talking to server\n");
return 1;
}
printf("It worked!\n");
L4Re::Util::cap_alloc.free(server, L4Re::This_task);
return 0;
}

View File

@@ -0,0 +1,76 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <stdio.h>
#include <l4/re/env>
#include <l4/re/util/cap_alloc>
#include <l4/re/util/object_registry>
#include <l4/cxx/ipc_server>
#include "shared.h"
static char page_to_map[L4_PAGESIZE] __attribute__((aligned(L4_PAGESIZE)));
static L4Re::Util::Registry_server<> server;
class Smap_server : public L4::Server_object_t<Mapper>
{
public:
int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
};
int
Smap_server::dispatch(l4_umword_t, L4::Ipc::Iostream &ios)
{
l4_msgtag_t t;
ios >> t;
// We're only talking the Map_example protocol
if (t.label() != Mapper::Protocol)
return -L4_EBADPROTO;
L4::Opcode opcode;
ios >> opcode;
switch (opcode)
{
case Mapper::Do_map:
l4_addr_t snd_base;
ios >> snd_base;
// put something into the page to read it out at the other side
snprintf(page_to_map, sizeof(page_to_map), "Hello from the server!");
printf("Sending to client\n");
// send page
ios << L4::Ipc::Snd_fpage::mem((l4_addr_t)page_to_map, L4_PAGESHIFT,
L4_FPAGE_RO, snd_base);
return L4_EOK;
default:
return -L4_ENOSYS;
}
}
int
main()
{
static Smap_server smap;
// Register server
if (!server.registry()->register_obj(&smap, "smap").is_valid())
{
printf("Could not register my service, read-only namespace?\n");
return 1;
}
printf("Welcome to the memory map example server!\n");
// Wait for client requests
server.loop();
return 0;
}

View File

@@ -0,0 +1,17 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/sys/capability>
struct Mapper : public L4::Kobject_t<Mapper, L4::Kobject>
{
enum Opcodes { Do_map };
};

View File

@@ -0,0 +1,21 @@
-- vim:set ft=lua:
-- Include L4 functionality
local L4 = require("L4");
-- Channel for the communication between the server and the client.
local smap_channel = L4.default_loader:new_channel();
-- The server program, using the 'smap' channel in server
-- mode. The log prefix will be 'server', colored yellow.
L4.default_loader:start({ caps = { smap = smap_channel:svr() },
log = { "server", "yellow" }},
"rom/ex_smap-server");
-- The client program.
-- It is given the 'smap' channel to be able to talk to the server.
-- The log prefix will be 'client', colored green.
L4.default_loader:start({ caps = { smap = smap_channel },
log = { "client", "green" } },
"rom/ex_smap-client");

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = uclibc_thread_safe
SRC_CC = main.cc
REQUIRES_LIBS = libpthread
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,100 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>,
* Frank Mehnert <fm3@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <pthread-l4.h>
#include <l4/util/util.h>
#include <l4/sys/kdebug.h>
#if defined(ARCH_x86) || defined(ARCH_amd64)
#include <l4/util/rdtsc.h>
#endif
#include <l4/re/env.h>
#include <pthread.h>
#include <l4/l4re_vfs/backend>
#if !defined(ARCH_x86) && !defined(ARCH_amd64)
static void l4_busy_wait_ns(unsigned long val)
{
static volatile int fooo = 0;
unsigned long i;
for (i = val/10; i > 0; --i)
++fooo;
}
#endif
static void *
thread(void *id)
{
printf("\033[31merrno_location[%ld] = %08lx\033[m\n",
(unsigned long)id, (l4_addr_t)__errno_location());
for (;;)
{
if (id == (void*)1)
puts("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
else
puts("ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ");
l4_busy_wait_ns(1000000);
}
return NULL;
}
namespace {
using namespace L4Re::Vfs;
class myops : public Be_file
{
public:
ssize_t writev(const struct iovec *i, int) throw();
int fstat64(struct stat64 *buf) const throw()
{ (void)buf; return 0; }
};
ssize_t
myops::writev(const struct iovec *i, int) throw()
{
const char *b = (char *)i->iov_base;
size_t c = i->iov_len;
while (c--)
{
outchar(*b++);
l4_busy_wait_ns(1000000);
}
return i->iov_len;
}
static void f() __attribute__((constructor));
static void f()
{
static myops mo;
mo.add_ref();
L4Re::Vfs::vfs_ops->set_fd(STDOUT_FILENO, cxx::ref_ptr(&mo));
}
}
int
main(void)
{
#if defined(ARCH_x86) || defined(ARCH_amd64)
l4_calibrate_tsc(l4re_kip());
#endif
dup2(STDOUT_FILENO, STDERR_FILENO);
pthread_t t1, t2;
pthread_create(&t1, NULL, thread, (void *)1);
pthread_create(&t2, NULL, thread, (void *)2);
l4_sleep_forever();
}

View File

@@ -0,0 +1,25 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
DEPENDS_PKGS = libgomp
# missing sync_* functions in (my) sparc compiler
SYSTEMS = $(filter-out sparc-l4f,$(SYSTEMS_ABI))
include $(L4DIR)/mk/Makeconf
ifneq ($(SYSTEM),)
# check whether used gcc has the omp.h file available
OMP_H_PATH := $(shell $(CC) -print-file-name=include/omp.h)
ifeq ($(strip $(OMP_H_PATH)),include/omp.h)
$(info  $(CC) does not have omp.h header file available, skipping.)
else
TARGET = $(if $(filter 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5,$(GCCVERSION)),ex_omp)
REQUIRES_LIBS = libgomp libc_support_misc
endif
endif
SRC_C = main.c
CFLAGS = -fopenmp
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,22 @@
#include <omp.h>
#include <stdio.h>
#include <semaphore.h>
int main(void)
{
int id, nthreads;
printf("Program launching\n");
#pragma omp parallel private (id)
{
id = omp_get_thread_num();
printf("Hello World from thread %d\n", id);
#pragma omp barrier
if (id == 0) {
nthreads = omp_get_num_threads();
printf("There are %d threads\n", nthreads);
}
}
printf("DONE\n");
return 1;
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_libio
SRC_C = main.c
REQUIRES_LIBS = libio libirq
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,90 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/io/io.h>
#include <l4/irq/irq.h>
#include <l4/util/util.h>
#include <l4/sys/kdebug.h>
#include <stdio.h>
void __libio_dump(void);
static void dump_vbus(void)
{
l4io_device_handle_t devhandle = l4io_get_root_device();
l4io_device_t dev;
l4io_resource_handle_t reshandle;
while (!l4io_iterate_devices(&devhandle, &dev, &reshandle))
{
l4io_resource_t res;
printf("device: type=%x name=%s numres=%d flags=%x\n",
dev.type, dev.name, dev.num_resources, dev.flags);
while (!l4io_lookup_resource(devhandle, L4IO_RESOURCE_ANY,
&reshandle, &res))
{
printf(" resource: %d %x %lx-%lx\n",
res.type, res.flags, res.start, res.end);
}
}
}
int main(void)
{
l4_addr_t a1, a2;
l4irq_t *irq12;
fprintf(stderr, "libio_test\n");
dump_vbus();
if (l4io_request_ioport(0x80, 1))
return 1;
fprintf(stderr, "%s %d\n", __func__, __LINE__);
if (l4io_request_ioport(0x90, 0xf))
return 1;
fprintf(stderr, "%s %d\n", __func__, __LINE__);
fprintf(stderr, "Ports 0x80 and 0x90-0x9e should be there\n");
if (!(irq12 = l4irq_attach(12)))
return -1;
if (l4io_request_iomem(0xfe000000, 0x100000, 0, &a1))
return 1;
fprintf(stderr, "0xfe000000 mapped to %lx\n", a1);
if (l4io_request_iomem(0xfa000000, 0x10000, 1, &a2))
return 1;
fprintf(stderr, "0xfa000000 mapped to %lx\n", a2);
fprintf(stderr, "Check mappings, IRQs and ports in JDB\n");
//__libio_dump();
enter_kdebug("check in jdb");
if (l4io_release_iomem(a1, 0x100000))
return 1;
if (l4io_release_ioport(0x90, 0xf))
return 1;
if (l4irq_detach(irq12))
return 1;
fprintf(stderr, "Check that region at %lx and I/O port range 0x90-0x9e and IRQ12 disappeared\n", a1);
//__libio_dump();
enter_kdebug("check in jdb");
return 0;
}

View File

@@ -0,0 +1,10 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
SRC_C_ex_libirq_async = async_isr.c
SRC_C_ex_libirq_loop = loop.c
TARGET = ex_libirq_async ex_libirq_loop
REQUIRES_LIBS = libirq libio
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,50 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
/*
* This example shall show how to use the libirq.
*/
#include <l4/irq/irq.h>
#include <l4/util/util.h>
#include <stdio.h>
enum { IRQ_NO = 17 };
static void isr_handler(void *data)
{
(void)data;
printf("Got IRQ %d\n", IRQ_NO);
}
int main(void)
{
const int seconds = 5;
l4irq_t *irqdesc;
if (!(irqdesc = l4irq_request(IRQ_NO, isr_handler, 0, 0xff, 0)))
{
printf("Requesting IRQ %d failed\n", IRQ_NO);
return 1;
}
printf("Attached to key IRQ %d\nPress keys now, will terminate in %d seconds\n",
IRQ_NO, seconds);
l4_sleep(seconds * 1000);
if (l4irq_release(irqdesc))
{
printf("Failed to release IRQ\n");
return 1;
}
printf("Bye\n");
return 0;
}

View File

@@ -0,0 +1,50 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/irq/irq.h>
#include <l4/util/util.h>
#include <stdio.h>
#include <pthread.h>
enum { IRQ_NO = 17 };
static void isr_handler(void)
{
printf("Got IRQ %d\n", IRQ_NO);
}
static void *isr_thread(void *data)
{
l4irq_t *irq;
(void)data;
if (!(irq = l4irq_attach(IRQ_NO)))
return NULL;
while (1)
{
if (l4irq_wait(irq))
continue;
isr_handler();
}
return NULL;
}
int main(void)
{
pthread_t thread;
if (pthread_create(&thread, NULL, isr_thread, NULL))
return 1;
l4_sleep_forever();
return 0;
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_libpng
SRC_C = main.c
REQUIRES_LIBS = libl4png_wrap l4re_c-util
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,80 @@
#include <l4/re/c/util/cap_alloc.h>
#include <l4/re/c/util/video/goos_fb.h>
#include <l4/libpng/l4png_wrap.h>
#include <l4/util/util.h>
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char **argv)
{
void *bildmem;
void *vidmem;
l4re_util_video_goos_fb_t gfb;
l4re_video_view_info_t fbi;
if (argc < 2)
{
printf("Need to give PNG picture to display\n");
return 1;
}
if (l4re_util_video_goos_fb_setup_name(&gfb, "fb"))
return 45;
if (!(vidmem = l4re_util_video_goos_fb_attach_buffer(&gfb)))
return 46;
printf("size: %lld\n", l4re_ds_size(l4re_util_video_goos_fb_buffer(&gfb)));
printf("Vidmem attached to %p\n", vidmem);
if (l4re_util_video_goos_fb_view_info(&gfb, &fbi))
{
printf("l4re_fb_open failed\n");
return 1;
}
int bild = open(argv[1], O_RDONLY);
if (bild == -1)
{
printf("Could not open '%s'.\n", argv[1]);
perror("open");
return 8;
}
struct stat st;
if (fstat(bild, &st) == -1)
return 9;
bildmem = mmap(0, st.st_size, PROT_READ, MAP_SHARED, bild, 0);
if (bildmem == MAP_FAILED)
return 10;
int png_w, png_h;
libpng_get_size_mem(bildmem, st.st_size, &png_w, &png_h);
printf("PNG: %dx%d\n", png_w, png_h);
if (png_w < 0 || png_h < 0)
{
printf("Error with picture. Is it one?\n");
return 1;
}
libpng_render_mem2(bildmem, (void *)vidmem,
st.st_size,
l4re_ds_size(l4re_util_video_goos_fb_buffer(&gfb)),
((int)fbi.width - png_w) / 2,
((int)fbi.height - png_h) / 2,
&fbi);
l4re_util_video_goos_fb_refresh(&gfb, 0, 0, png_w, png_h);
l4_sleep_forever();
return 0;
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
SRC_C = main.c
TARGET = rtc_test
DEPENDS_PKGS = rtc
REQUIRES_LIBS = rtc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,43 @@
/**
* \file
* \brief Small RTC server test
*/
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/rtc/rtc.h>
#include <l4/util/util.h>
#include <l4/re/env.h>
#include <stdio.h>
int main(void)
{
l4_uint64_t value;
l4_cap_idx_t server = l4re_env_get_cap("rtc");
if (!l4_is_valid_cap(server))
{
printf("Error finding 'rtc' cap.\n");
return 1;
}
if (l4rtc_get_offset_to_realtime(server, &value))
printf("Error: l4rtc_get_offset_to_realtime\n");
else
printf("offset-to-realtime: %lld\n", value);
while (1)
{
l4_uint64_t now = l4rtc_get_timer() + value;
printf("time: %lldns\n", now);
l4_sleep(400);
}
return 0;
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_shmc
SRC_C = prodcons.c
REQUIRES_LIBS = shmc libpthread
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,192 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
/*
* This example uses shared memory between two threads, one producer, one
* consumer.
*/
#include <l4/shmc/shmc.h>
#include <l4/util/util.h>
#include <stdio.h>
#include <string.h>
#include <pthread-l4.h>
#include <l4/sys/thread.h>
#include <l4/sys/debugger.h>
#include <l4/sys/kip.h>
#include <l4/re/env.h>
#define LOG(args...) printf(NAME ": " args)
#define CHK(func) \
do \
{ \
long r = (func); \
if (r) \
{ \
printf(NAME ": Failure %ld (%s) at line %d.\n", \
r, l4sys_errtostr(r), __LINE__); \
return (void *)-1; \
} \
} while (0)
static const char some_data[] = "Hi consumer!";
static inline l4_cap_idx_t self(void) { return pthread_l4_cap(pthread_self()); }
#define NAME "PRODUCER"
static void *thread_producer(void *d)
{
(void)d;
l4shmc_chunk_t p_one;
l4shmc_signal_t s_one, s_done;
l4shmc_area_t shmarea;
l4_kernel_clock_t try_until;
l4_debugger_set_object_name(self(), "producer");
// attach this thread to the shm object
CHK(l4shmc_attach("testshm", &shmarea));
// add a chunk
CHK(l4shmc_add_chunk(&shmarea, "one", 1024, &p_one));
// add a signal
CHK(l4shmc_add_signal(&shmarea, "testshm_prod", &s_one));
CHK(l4shmc_attach_signal(&shmarea, "testshm_done", self(), &s_done));
// connect chunk and signal
CHK(l4shmc_connect_chunk_signal(&p_one, &s_one));
CHK(l4shmc_mark_client_initialized(&shmarea));
try_until = l4_kip_clock(l4re_kip()) + 10 * 1000000;
for (;;)
{
l4_umword_t clients;
l4shmc_get_initialized_clients(&shmarea, &clients);
if (clients == 3UL)
break;
if (l4_kip_clock(l4re_kip()) >= try_until)
{
LOG("consumer not initialized within time\n");
return (void *)-1;
}
}
LOG("Ready.\n");
while (1)
{
while (l4shmc_chunk_try_to_take(&p_one))
printf("Uh, should not happen!\n"); //l4_thread_yield();
memcpy(l4shmc_chunk_ptr(&p_one), some_data, sizeof(some_data));
CHK(l4shmc_chunk_ready_sig(&p_one, sizeof(some_data)));
LOG("Sent data.\n");
CHK(l4shmc_wait_signal(&s_done));
}
l4_sleep_forever();
return NULL;
}
#undef NAME
#define NAME "CONSUMER"
static void *thread_consumer(void *d)
{
(void)d;
l4shmc_area_t shmarea;
l4shmc_chunk_t p_one;
l4shmc_signal_t s_one, s_done;
l4_kernel_clock_t try_until;
l4_debugger_set_object_name(self(), "consumer");
// attach to shared memory area
CHK(l4shmc_attach("testshm", &shmarea));
// get chunk 'one'
CHK(l4shmc_get_chunk(&shmarea, "one", &p_one));
// add a signal
CHK(l4shmc_add_signal(&shmarea, "testshm_done", &s_done));
// attach signal to this thread
CHK(l4shmc_attach_signal(&shmarea, "testshm_prod", self(), &s_one));
// connect chunk and signal
CHK(l4shmc_connect_chunk_signal(&p_one, &s_one));
CHK(l4shmc_mark_client_initialized(&shmarea));
try_until = l4_kip_clock(l4re_kip()) + 10 * 1000000;
for (;;)
{
l4_umword_t clients;
l4shmc_get_initialized_clients(&shmarea, &clients);
if (clients == 3UL)
break;
if (l4_kip_clock(l4re_kip()) >= try_until)
{
LOG("producer not initialized within time\n");
return (void *)-1;
}
}
LOG("Ready.\n");
while (1)
{
CHK(l4shmc_wait_chunk(&p_one));
LOG("Received from chunk one: '%s'.\n",
(char *)l4shmc_chunk_ptr(&p_one));
memset(l4shmc_chunk_ptr(&p_one), 0, l4shmc_chunk_size(&p_one));
CHK(l4shmc_chunk_consumed(&p_one));
CHK(l4shmc_trigger(&s_done));
}
return NULL;
}
int main(void)
{
pthread_t one, two;
long r;
// create shared memory area
if ((r = l4shmc_create("testshm")) < 0)
{
printf("Error %ld (%s) creating shared memory area\n",
r, l4sys_errtostr(r));
return 1;
}
// create two threads, one for producer, one for consumer
pthread_create(&one, 0, thread_producer, 0);
pthread_create(&two, 0, thread_consumer, 0);
// now sleep, the two threads are doing the work
l4_sleep_forever();
return 0;
}

View File

@@ -0,0 +1,22 @@
-- vi:ft=lua
local L4 = require "L4";
-- The IRQ capabilities need the 'S' right to allow threads to attach to the
-- corresponding objects.
local irq_prod = L4.Env.factory:create(L4.Proto.Irq_sender)
local irq_done = L4.Env.factory:create(L4.Proto.Irq_sender)
local shm = L4.Env.user_factory:create(L4.Proto.Dataspace, 8192)
L4.default_loader:start(
{
caps =
{
jdb = L4.Env.jdb,
testshm_prod = irq_prod:m("rws"),
testshm_done = irq_done:m("rws"),
testshm = shm:m("rw"),
},
log = {"ex_shmc", "c"}
}, "rom/ex_shmc")

View File

@@ -0,0 +1,61 @@
# cyclichpet, eb_leds, eb_leds_gfx, hpet
optional: libio
# cyclichpet, hpet
optional: libirq
# cyclichpet
optional: libdrivers_hpet
# eb_leds_gfx, malloc-test
optional: libpthread
# eb_leds_gfx
optional: scout-gfx
# event_dump
requires: l4re
# fbreboot, lobacc, marvin
optional: libgfxbitmap libstdc++ libevent
# fbreboot, magbag
optional: libpng mag-gfx
# fbreboot
optional: libgfxbitmap-support libevent
# fortran-hello, fortran-omp
optional: libgfortran
# fortran-omp
optional: libgomp
# inhibitor, pwr
optional: libio-vbus
# lobacc
optional: libloba
# luash, marvin
optional: readline libc_be_fs_noop libc_support_misc
# luash
optional: lua
# magbag
optional: cxx_libc_io cxx_io
# hello-shared
requires: stdlibs-sh
# tarfs
optional: libl4revfs-fs-tarfs libmount libstdc++
# tbuf
optional: libtbuf
# uhello
requires: l4sys
Maintainer: adam@os.inf.tu-dresden.de

View File

@@ -0,0 +1,6 @@
PKGDIR = .
L4DIR ?= $(PKGDIR)/../../..
TARGET = $(wildcard [a-z]*)
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,7 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = cat
SRC_C = cat.c
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,43 @@
/**
* \file
* \brief A cat.
*
* \date
* \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
*
*/
/*
* (c) 2009 Author(s)
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <stdio.h>
int main(int argc, char **argv)
{
int i;
FILE *fp;
char buf[1024];
size_t r;
for (i = 1; i < argc; ++i)
{
fp = fopen(argv[i], "r");
if (!fp)
{
perror(argv[i]);
continue;
}
while ((r = fread(buf, 1, sizeof(buf), fp)))
fwrite(buf, 1, r, stdout);
fclose(fp);
}
return 0;
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_eb_leds
SRC_C = eb_leds.c
REQUIRES_LIBS = libio
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,104 @@
/* SPDX-License-Identifier: MIT */
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
*/
/*
* The ARM EB boards have 8 LEDs which we can play a bit with. This example
* shows how to get access to the I/O memory...
*/
#include <l4/io/io.h>
#include <stdio.h>
#include <time.h>
enum {
USERSW = 0x4,
LED = 0x8,
};
static l4_addr_t sys_base;
static void write_led(int val)
{
*(volatile unsigned long *)(sys_base + LED) = val & 0xff;
}
static unsigned char read_user_switch(void)
{
/* only 8 switches there, so char return is enough */
return *(volatile unsigned long *)(sys_base + USERSW);
}
static void do_fancy(char val)
{
int mode = val & 0x80;
int speed = val & 0x7f;
if (!mode)
{
static int pos, delta = 1;
write_led(1 << pos);
pos += delta;
if (pos == 7)
delta = -1;
else if (pos == 0)
delta = 1;
}
else
{
static int pos, delta = 1;
write_led((1 << pos) | (1 << (7 - pos)));
pos += delta;
if (pos == 3)
delta = -1;
else if (pos == 0)
delta = 1;
}
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = (500000 / (speed + 1)) * 1000;
nanosleep(&ts, NULL);
}
int main(void)
{
l4io_device_handle_t dh;
l4io_resource_handle_t hdl;
char prev = 0;
/* Look for system controller, the registers we want are there */
if (l4io_lookup_device("System Control", &dh, 0, &hdl))
{
printf("Could not get system controller memory region.\n");
return 1;
}
/* Now get the IO memory from it. We know that it just has one memory
* region, so we just do this one once: */
sys_base = l4io_request_resource_iomem(dh, &hdl);
if (sys_base == 0)
{
printf("Could not map system controller region.\n");
return 1;
}
printf("User Switches (toggle them now but don't forget their initial setting!):\n");
while (1)
{
int i;
char val = read_user_switch();
if (prev != val)
{
for (i = 0; i < 8; ++i)
printf("%s ", val & (1 << i) ? "ON " : "off");
printf("\n");
prev = val;
}
do_fancy(val);
}
return 0;
}

View File

@@ -0,0 +1,10 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = fortran-hello
SRC_F = main.f90
REQUIRES_LIBS = libgfortran
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,7 @@
! -*- Mode: F90 -*-
program hello
print *, "Hello World!"
end program hello
! EOF

View File

@@ -0,0 +1,7 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = reboot
SRC_C = main.c
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright (C) 2020, 2024 Kernkonzept GmbH.
* Author(s): Sarah Hoffmann <sarah.hoffmann@kernkonzept.com>
*
*/
/*
* \brief Just reboot
* \date 2006-03
* \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
*
* (c) 2006-2009 Author(s)
*/
#include <l4/re/env.h>
#include <l4/sys/platform_control.h>
int main(void)
{
l4_cap_idx_t pfc = l4re_env_get_cap("pfc");
if (l4_is_valid_cap(pfc))
l4_platform_ctl_system_shutdown(pfc, 1);
return 0;
}

View File

@@ -0,0 +1,8 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_hello_shared
MODE = shared
SRC_C = main.c
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,28 @@
/*
* \brief A 'hello' program linked against shared libraries.
* \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
*
* This program is built with shared libraries.
*/
/*
* (c) 2009 Author(s)
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <stdio.h>
#include <unistd.h>
int main(void)
{
while (1)
{
puts("Hi World! (shared)");
sleep(1);
}
return 0;
}

View File

@@ -0,0 +1,24 @@
requires: stdlibs
# aliens, isr, singlestep, start-with-exc, utcb-ipc, vm-tz
optional: l4re_c-util
# ipc, migrate, uirq
optional: libpthread
# uirq
optional: libstdc++
# vcpu, vmtest, vm-tz
optional: libvcpu
# vcpu
optional: cxx_io cxx_libc_io
# vmtest
optional: l4util
# vm-tz
optional: libsigma0
Maintainer: adam@os.inf.tu-dresden.de

View File

@@ -0,0 +1,6 @@
PKGDIR = .
L4DIR ?= $(PKGDIR)/../../..
TARGET = $(wildcard [a-z]*)
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_aliens
SRC_C = main.c
REQUIRES_LIBS = l4re_c-util
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,302 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>,
* Björn Döbel <doebel@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
/*
* Example to show syscall tracing.
*/
#if defined(ARCH_x86) || defined(ARCH_amd64)
// MEASURE only works on x86/amd64
//#define MEASURE
#endif
#include <l4/sys/ipc.h>
#include <l4/sys/thread.h>
#include <l4/sys/factory.h>
#include <l4/sys/utcb.h>
#include <l4/util/util.h>
#include <l4/re/env.h>
#include <l4/re/c/util/cap_alloc.h>
#include <l4/re/c/util/kumem_alloc.h>
#include <l4/sys/debugger.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* Architecture specifics */
#if defined(ARCH_x86) || defined(ARCH_amd64)
static int
is_alien_after_call(l4_exc_regs_t const *exc)
{
#if defined(ARCH_x86)
return exc->err & 4;
#else
return exc->err == 1;
#endif
}
static inline void
_print_exc_state(l4_exc_regs_t const *exc)
{
printf("PC=%08lx SP=%08lx Err=%08lx Trap=%lx, %s syscall, SC-Nr: %lx\n",
l4_utcb_exc_pc(exc), exc->sp, exc->err,
exc->trapno, is_alien_after_call(exc) ? " after" : "before",
exc->err >> 3);
}
#elif defined(ARCH_arm)
static int
is_alien_after_call(l4_exc_regs_t const *exc)
{ return exc->err & 0x40; } // TODO: Should change this to (1 << 16)
static inline void
_print_exc_state(l4_exc_regs_t const *exc)
{
printf("PC=%08lx SP=%08lx ULR=%08lx CPSR=%08lx Err=%lx/%lx, %s syscall\n",
l4_utcb_exc_pc(exc), exc->sp, exc->ulr, exc->cpsr,
exc->err, exc->err >> 26,
is_alien_after_call(exc) ? " after" : "before");
}
#elif defined(ARCH_arm64)
static int
is_alien_after_call(l4_exc_regs_t const *exc)
{ return exc->err & (1ul << 16); }
static inline void
_print_exc_state(l4_exc_regs_t const *exc)
{
printf("PC=%08lx SP=%08lx PSTATE=%08lx Err=%lx/%lx, %s syscall\n",
l4_utcb_exc_pc(exc), exc->sp, exc->pstate,
exc->err, exc->err >> 26,
is_alien_after_call(exc) ? " after" : "before");
}
#elif defined(ARCH_mips)
static int
is_alien_after_call(l4_exc_regs_t const *exc)
{ return 0; }
static inline void
_print_exc_state(l4_exc_regs_t const *exc)
{
printf("PC=%08lx SP=%08lx Cause=%lx, %s syscall\n",
l4_utcb_exc_pc(exc), exc->sp, exc->cause,
is_alien_after_call(exc) ? " after" : "before");
}
#elif defined(ARCH_riscv)
static int
is_alien_after_call(l4_exc_regs_t const *exc)
{ return exc->cause == L4_riscv_ec_l4_alien_after_syscall; }
static inline void
_print_exc_state(l4_exc_regs_t const *exc)
{
printf("PC=%08lx SP=%08lx Cause=%lx, %s syscall\n",
l4_utcb_exc_pc(exc), exc->sp, exc->cause,
is_alien_after_call(exc) ? " after" : "before");
}
#else
static int
is_alien_after_call(l4_exc_regs_t const *exc)
{ return exc->err & 1; }
static inline void
_print_exc_state(l4_exc_regs_t const *exc)
{
printf("PC=%08lx SP=%08lx, %s syscall\n",
l4_utcb_exc_pc(exc), exc->sp,
is_alien_after_call(exc) ? " after" : "before");
}
#endif
/* Measurement mode specifics.
*
* In measurement mode the code is less verbose and uses RDTSC for alient exception
* performance measurement.
*/
#ifdef MEASURE
#include <l4/util/rdtsc.h>
static inline void
calibrate_timer(void)
{
l4_calibrate_tsc(l4re_kip());
}
static inline void
print_timediff(l4_cpu_time_t start)
{
e = l4_rdtsc();
printf("time %lld\n", l4_tsc_to_ns(e - start));
}
static inline void
alien_sleep(void)
{
l4_sleep(0);
}
static inline void
print_exc_state(l4_exc_regs_t const *exc)
{
if (0)
_print_exc_state(exc);
}
#else
static inline void
calibrate_timer(void)
{
}
static inline void
print_timediff(l4_cpu_time_t start)
{
(void)start;
}
static inline l4_cpu_time_t
l4_rdtsc(void)
{
return 0;
}
static inline void
alien_sleep(void)
{
l4_sleep(1000);
}
static inline void
print_exc_state(l4_exc_regs_t const *exc)
{
_print_exc_state(exc);
}
#endif
static char alien_thread_stack[8 << 10];
static l4_cap_idx_t alien;
static void alien_thread(void)
{
while (1)
{
l4_ipc_call(0x1234 << L4_CAP_SHIFT, l4_utcb(),
l4_msgtag(0, 0, 0, 0), L4_IPC_NEVER);
alien_sleep();
}
}
int main(void)
{
l4_msgtag_t tag;
l4_cpu_time_t s;
l4_utcb_t *u = l4_utcb();
l4_exc_regs_t exc;
l4_umword_t mr0, mr1;
printf("Alien feature testing\n");
l4_debugger_set_object_name(l4re_env()->main_thread, "alientest");
/* Start alien thread */
if (l4_is_invalid_cap(alien = l4re_util_cap_alloc()))
return 1;
l4_touch_rw(alien_thread_stack, sizeof(alien_thread_stack));
tag = l4_factory_create_thread(l4re_env()->factory, alien);
if (l4_error(tag))
return 2;
l4_debugger_set_object_name(alien, "alienth");
l4_addr_t kumem;
if (l4re_util_kumem_alloc(&kumem, 0, L4RE_THIS_TASK_CAP, l4re_env()->rm))
return 3;
l4_thread_control_start();
l4_thread_control_pager(l4re_env()->main_thread);
l4_thread_control_exc_handler(l4re_env()->main_thread);
l4_thread_control_bind((l4_utcb_t *)kumem, L4RE_THIS_TASK_CAP);
l4_thread_control_alien(1);
tag = l4_thread_control_commit(alien);
if (l4_error(tag))
return 4;
tag = l4_thread_ex_regs(alien,
(l4_umword_t)alien_thread,
(l4_umword_t)alien_thread_stack + sizeof(alien_thread_stack),
0);
if (l4_error(tag))
return 5;
l4_sched_param_t sp = l4_sched_param(1, 0);
tag = l4_scheduler_run_thread(l4re_env()->scheduler, alien, &sp);
if (l4_error(tag))
return 6;
calibrate_timer();
/* Pager/Exception loop */
if (l4_msgtag_has_error(tag = l4_ipc_receive(alien, u, L4_IPC_NEVER)))
{
printf("l4_ipc_receive failed");
return 7;
}
memcpy(&exc, l4_utcb_exc(), sizeof(exc));
mr0 = l4_utcb_mr()->mr[0];
mr1 = l4_utcb_mr()->mr[1];
for (;;)
{
s = l4_rdtsc();
if (l4_msgtag_is_exception(tag))
{
print_exc_state(&exc);
tag = l4_msgtag(is_alien_after_call(&exc)
? 0 : L4_PROTO_ALLOW_SYSCALL,
L4_UTCB_EXCEPTION_REGS_SIZE, 0, 0);
}
else
printf("Umm, non-handled request (like PF): %lx %lx\n", mr0, mr1);
memcpy(l4_utcb_exc(), &exc, sizeof(exc));
/* Reply and wait */
if (l4_msgtag_has_error(tag = l4_ipc_call(alien, u, tag, L4_IPC_NEVER)))
{
printf("l4_ipc_call failed\n");
return 8;
}
memcpy(&exc, l4_utcb_exc(), sizeof(exc));
mr0 = l4_utcb_mr()->mr[0];
mr1 = l4_utcb_mr()->mr[1];
print_timediff(s);
}
return 0;
}

View File

@@ -0,0 +1,7 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = dump_obj
SRC_CC = dump_obj.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,159 @@
#include <cstdio>
#include <l4/sys/debugger.h>
#include <l4/sys/obj_info.h>
#include <l4/re/error_helper>
#include <l4/re/util/kumem_alloc>
int main()
{
enum
{
Order_kumem_pages = 4,
Size_kumem = L4_PAGESIZE << Order_kumem_pages,
};
l4_addr_t kumem;
L4Re::chksys(L4Re::Util::kumem_alloc(&kumem, Order_kumem_pages),
"Allocate KU memory for object information");
unsigned skip_entries = 0;
for (;;)
{
l4_umword_t result_cnt;
l4_umword_t result_all;
L4Re::chksys(l4_debugger_query_obj_infos(L4_BASE_DEBUGGER_CAP,
kumem, Size_kumem, skip_entries,
&result_cnt, &result_all),
"Retrieve kernel object information");
if (skip_entries == 0)
printf("\033[31mGot %lu/%lu entries during first call.\033[m\n",
result_cnt, result_all);
if (result_cnt == 0)
break;
auto const *o = reinterpret_cast<L4_kobj_info *>(kumem);
for (unsigned i = 0; i < result_cnt; ++i, ++o)
{
if (o->type != L4_kobj_info::Mapping::Type)
printf("%llx %llx ", o->id, o->mapping_ptr);
switch (o->type)
{
case L4_kobj_info::Mapping::Type:
printf("%*s%0*lx[C:%x]: space=D:%llx%s%.*s%s rights=%x flags=%x obj=0x%llx",
8, "",
sizeof(l4_umword_t) == 8 ? 16 : 8,
(l4_umword_t)o->mapping.mapping_ptr,
o->mapping.cap_idx,
o->id,
o->mapping.space_name[0] ? "(" : "",
o->mapping.space_name[0] ? int{sizeof(o->mapping.space_name)} : 0,
o->mapping.space_name[0] ? o->mapping.space_name : "",
o->mapping.space_name[0] ? ")" : "",
o->mapping.entry_rights,
o->mapping.entry_flags,
o->mapping.entry_ptr);
break;
case L4_kobj_info::Thread::Type:
printf("[\033[32mThread\033[m]%s C=%u",
o->thread.is_kernel ? " {KERNEL}" : "",
o->thread.home_cpu);
if (o->thread.home_cpu != o->thread.current_cpu)
printf(":%u", o->thread.current_cpu);
if (o->thread.is_kernel_task)
printf(" R=%lld rdy%s",
o->thread.ref_cnt,
o->thread.is_current ? " \033[32mcur\033[m" : "");
else
printf(" S=D:%llx R=%lld%s%s",
o->thread.space_id,
o->thread.ref_cnt,
o->thread.in_ready_list ? " rdy" : "",
o->thread.is_current ? " \033[32mcur\033[m" : "");
break;
case L4_kobj_info::Space::Type:
printf("[\033[31mTask\033[m]%s R=%lld",
o->space.is_kernel ? " {KERNEL}" : "",
o->space.ref_cnt);
break;
case L4_kobj_info::Vm::Type:
printf("Vm:");
break;
case L4_kobj_info::Ipc_gate::Type:
printf("[\033[35mGate\033[m] L=%s%08llx\033[m D=%llx",
o->ipc_gate.label & 3 ? "\033[36;1m" : "",
o->ipc_gate.label,
o->ipc_gate.thread_id);
break;
case L4_kobj_info::Irq_sender::Type:
printf("[\033[37mIRQ ipc\033[m] I=%x %.*s F=%x L=%llx T=%llx Q=%lld",
o->irq_sender.pin,
int{sizeof(o->irq_sender.chip_type)},
o->irq_sender.chip_type,
o->irq_sender.flags,
o->irq_sender.label,
o->irq_sender.target_id,
o->irq_sender.queued);
break;
case L4_kobj_info::Irq_semaphore::Type:
printf("[\033[37mIRQ sem\033[m] I=%x %.*s F=%x Q=%lld",
o->irq_semaphore.pin,
int{sizeof(o->irq_semaphore.chip_type)},
o->irq_semaphore.chip_type,
o->irq_semaphore.flags,
o->irq_semaphore.queued);
break;
case L4_kobj_info::Factory::Type:
printf("\033[33;1mFactory\033[m c=%llu l=%llu",
o->factory.current,
o->factory.limit);
break;
case L4_kobj_info::Jdb::Type:
printf("[Jdb]");
break;
case L4_kobj_info::Scheduler::Type:
printf("[\033[34mSched\033[m]");
break;
case L4_kobj_info::Vlog::Type:
printf("[Vlog]");
break;
case L4_kobj_info::Pfc::Type:
printf("[Icu/Pfc]");
break;
case L4_kobj_info::Dmar_space::Type:
printf("[IOMMU]");
break;
case L4_kobj_info::Iommu::Type:
printf("[IOMMU]");
break;
case L4_kobj_info::Smmu::Type:
printf("[SMMU]");
break;
}
if (o->type != L4_kobj_info::Mapping::Type)
printf(" ref_cnt=%lld", o->ref_cnt);
printf("\n");
}
skip_entries += result_cnt;
}
printf("\nFinished!\n");
return 0;
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_ipc1
SRC_C = ipc_example.c
REQUIRES_LIBS = libpthread
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

Some files were not shown because too many files have changed in this diff Show More