Tag Sculpt 19.07

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCgAGBQJdJGPtAAoJEKckYDQX7Na3/3oP/3fgZKXRiFaSi0IWDX5leBLx
 bkKgqnnS9KRRLSIibOTZSOBE+HfIUb6gOr4Md1sdM9NILIF+R33cwPc8OUL4nsbc
 tefzgNCCtuDUmLTebDWrEE6Hz1ZJwUiXMOE3ACC/9zoMo9/lg1AQreK5QWt/+jDO
 JTH2SofQOeJjfme90qcJo0x/xg9/ARZzQLiPXigtlwWUEP6b0sA0q1wbcMZb4fyG
 14oOJew/9/3ARawvzw18oSCW1hAQyrDnP0Lm9N/i1vi+mcJc7uBFojXeEKe8IudM
 rq+5NRwj7hV2GfiujVb2MbdM6JpFT5dhUP5pyFDjUd5CuDxpAslYqCBRz7OJQNjz
 a28inTbRucbUDeca7jIg6/IUjpqFyRjWDcmh2ChUbJHWddNeh+8N7bJQUguJmlEL
 XrHeiPEGEbkhofZ7cUHUKbxOtpr+YAonyxSwoKCPWa5Co20E2NOl3C8bAuPZzJxI
 ij+PiPwG79dfW+Q24gV6OImzCeUbTcVibo/GodtySapfdTamE8fdEfgfMEjyPzj4
 2doK3Ufk2oN5XRIyThNErcgTj4Cm6zzhvocKt5Rk31d0FbKpDNM+aDwRMLMcCTTf
 lw8yYMjuFtEkGzQ1612VNB5occR4djx1TtG8EYF7aJ8hf+klpprM2/A4Uj4J6WIw
 M64j4W9LbVM5cj9ynL/m
 =ldp5
 -----END PGP SIGNATURE-----

Merge tag 'sculpt-19.07' into submodule
This commit is contained in:
Ehmry - 2019-07-10 13:54:08 +02:00
commit acbbb3ebe8
113 changed files with 2428 additions and 3926 deletions

View File

@ -16,70 +16,49 @@
.global _start
_start:
/****************
** Enable FPU **
****************/
mov x0, #0b11
lsl x0, x0, #20
msr cpacr_el1, x0
/***********************
** Detect CPU number **
***********************/
mrs x0, mpidr_el1
and x0, x0, #0b11111111
cmp x0, #0
bne __endless_sleep
cbz x0, _crt0_fill_bss_zero
wfe
b _start
/***************************
** Zero-fill BSS segment **
***************************/
ldr x0, =_bss_local_start
ldr x1, =_bss_local_end
_crt0_fill_bss_zero:
ldr x0, =_bss_start
ldr x1, =_bss_end
1:
cmp x1, x0
ble 2f
str xzr, [x0]
add x0, x0, #8
b 1b
2:
b.eq _crt0_enable_fpu
str xzr, [x0], #8
b 1b
/************************************
** Jump to high-level entry point **
************************************/
/****************
** Enable FPU **
****************/
ldr x0, =_start_stack /* load stack address into x0 */
msr vbar_el1, x0
_crt0_enable_fpu:
mov x0, #0b11
lsl x0, x0, #20
msr cpacr_el1, x0
/**********************
** Initialize stack **
**********************/
ldr x0, =_crt0_start_stack
mov sp, x0
bl init
__endless_sleep:
wfe
1: b 1b
_bss_local_start:
.quad _bss_start
_bss_local_end:
.quad _bss_end
.p2align 4
.space 0x4000
_start_stack:
.rept 512
nop
.endr
mrs x24, far_el1
mrs x25, ttbr0_el1
mrs x26, ttbr1_el1
mrs x27, elr_el1
mrs x28, esr_el1
1: b 1b
_crt0_start_stack:

View File

@ -133,6 +133,7 @@ unsigned Bootstrap::Platform::enable_mmu()
Cpu::Sctlr_el1::access_t sctlr = Cpu::Sctlr_el1::read();
Cpu::Sctlr_el1::C::set(sctlr, 1);
Cpu::Sctlr_el1::I::set(sctlr, 1);
Cpu::Sctlr_el1::A::set(sctlr, 0);
Cpu::Sctlr_el1::M::set(sctlr, 1);
Cpu::Sctlr_el1::Sa0::set(sctlr, 1);

View File

@ -106,11 +106,12 @@ struct Hw::Arm_64_cpu
);
SYSTEM_REGISTER(64, Sctlr_el1, sctlr_el1,
struct M : Bitfield<0, 1> { };
struct A : Bitfield<1, 1> { };
struct C : Bitfield<2, 1> { };
struct Sa : Bitfield<3, 1> { };
struct Sa0 : Bitfield<4, 1> { };
struct M : Bitfield<0, 1> { };
struct A : Bitfield<1, 1> { };
struct C : Bitfield<2, 1> { };
struct Sa : Bitfield<3, 1> { };
struct Sa0 : Bitfield<4, 1> { };
struct I : Bitfield<12, 1> { };
);
struct Spsr : Genode::Register<64>

View File

@ -66,30 +66,33 @@ void Genode::print_lines(char const *string, size_t len, FUNC const &func)
if (Genode::strcmp(first_line, string, num_indent_chars) == 0)
string += num_indent_chars;
size_t const line_len =
({
size_t i = 0;
for (; i < len; i++) {
if (string[i] == '\0' || string[i] == '\n') {
size_t line_len = 0;
size_t skip_char = 1;
/* the line length is the offset of the last real character + 1 */
i++;
break;
}
}
i;
});
for (; line_len < len; line_len++) {
if (string[line_len] == '\0' || string[line_len] == '\n') {
line_len++;
break;
}
if (line_len == MAX_LINE_LEN) {
skip_char = 0;
break;
}
}
if (!line_len)
break;
/*
* Copy line from (untrusted) caller to local line buffer
*/
char line_buf[MAX_LINE_LEN];
Genode::strncpy(line_buf, string, Genode::min(line_len, sizeof(line_buf)));
/* buffer for sub-string of the input string plus null-termination */
char line_buf[MAX_LINE_LEN + 1];
/* give strncpy one more as it will add the null termination */
Genode::strncpy(line_buf, string, line_len - skip_char + 1);
/* process null-terminated string in buffer */
func(line_buf);
/* move forward to the next sub-string to process */
string += line_len;
len -= line_len;
}

View File

@ -391,7 +391,7 @@ struct Linker::Binary : private Root_object, public Elf_object
{
Init::list()->exec_static_constructors();
/* call static construtors and register destructors */
/* call static constructors and register destructors */
Func * const ctors_start = (Func *)lookup_symbol("_ctors_start");
Func * const ctors_end = (Func *)lookup_symbol("_ctors_end");
for (Func * ctor = ctors_end; ctor != ctors_start; (*--ctor)());
@ -677,10 +677,6 @@ void Genode::init_ldso_phdr(Env &env)
void Genode::exec_static_constructors()
{
if (!binary_ptr->static_construction_pending())
warning("Don't call Genode::Env::exec_static_constructors() "
"in components without static globals");
binary_ptr->finish_static_construction();
}

View File

@ -2,8 +2,13 @@ linux-x.x.x/drivers/net/ethernet/freescale/fec.h
linux-x.x.x/drivers/net/ethernet/freescale/fec_main.c
linux-x.x.x/drivers/net/ethernet/freescale/fec_ptp.c
linux-x.x.x/drivers/net/phy/mdio_bus.c
linux-x.x.x/drivers/net/phy/mdio_device.c
linux-x.x.x/drivers/net/phy/mdio-boardinfo.c
linux-x.x.x/drivers/net/phy/mdio-boardinfo.h
linux-x.x.x/drivers/net/phy/phy_device.c
linux-x.x.x/drivers/net/phy/phy.c
linux-x.x.x/drivers/net/phy/phy-c45.c
linux-x.x.x/drivers/net/phy/phy-core.c
linux-x.x.x/drivers/net/phy/at803x.c
linux-x.x.x/net/core/skbuff.c
linux-x.x.x/net/ethernet/eth.c
@ -14,21 +19,26 @@ linux-x.x.x/include/asm-generic/bitops/__fls.h
linux-x.x.x/include/asm-generic/bitops/ffs.h
linux-x.x.x/include/asm-generic/bitops/fls.h
linux-x.x.x/include/asm-generic/bitops/fls64.h
linux-x.x.x/include/linux/cgroup-defs.h
linux-x.x.x/include/linux/errqueue.h
linux-x.x.x/include/linux/ethtool.h
linux-x.x.x/include/linux/fec.h
linux-x.x.x/include/linux/gpio/consumer.h
linux-x.x.x/include/linux/if_ether.h
linux-x.x.x/include/linux/list.h
linux-x.x.x/include/linux/list_nulls.h
linux-x.x.x/include/linux/log2.h
linux-x.x.x/include/linux/mdio.h
linux-x.x.x/include/linux/mii.h
linux-x.x.x/include/linux/mod_devicetable.h
linux-x.x.x/include/linux/net.h
linux-x.x.x/include/linux/netdev_features.h
linux-x.x.x/include/linux/phy.h
linux-x.x.x/include/linux/ptp_clock_kernel.h
linux-x.x.x/include/linux/rbtree.h
linux-x.x.x/include/linux/rculist.h
linux-x.x.x/include/linux/rculist_nulls.h
linux-x.x.x/include/linux/refcount.h
linux-x.x.x/include/linux/skbuff.h
linux-x.x.x/include/linux/socket.h
linux-x.x.x/include/linux/timecounter.h

View File

@ -0,0 +1,34 @@
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 74664a6..38cc18a 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -944,7 +944,10 @@ EXPORT_SYMBOL(phy_attached_print);
int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
u32 flags, phy_interface_t interface)
{
+#if 0
+ /* 'driver' has not been set yet on Genode */
struct module *ndev_owner = dev->dev.parent->driver->owner;
+#endif
struct mii_bus *bus = phydev->mdio.bus;
struct device *d = &phydev->mdio.dev;
bool using_genphy = false;
@@ -955,7 +958,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
* our own module->refcnt here, otherwise we would not be able to
* unload later on.
*/
- if (ndev_owner != bus->owner && !try_module_get(bus->owner)) {
+ if (/*ndev_owner != bus->owner &&*/ !try_module_get(bus->owner)) {
dev_err(&dev->dev, "failed to get the bus module\n");
return -EIO;
}
@@ -1060,7 +1063,9 @@ error_module_put:
module_put(d->driver->owner);
error_put_device:
put_device(d);
+#if 0
if (ndev_owner != bus->owner)
+#endif
module_put(bus->owner);
return err;
}

View File

@ -1,28 +0,0 @@
diff --git a/include/net/sock.h b/include/net/sock.h
index 14d3c07..818a1d1 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2148,8 +2148,8 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
*/
if (sock_flag(sk, SOCK_RCVTSTAMP) ||
(sk->sk_tsflags & SOF_TIMESTAMPING_RX_SOFTWARE) ||
- (kt.tv64 && sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) ||
- (hwtstamps->hwtstamp.tv64 &&
+ (kt && sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) ||
+ (hwtstamps->hwtstamp &&
(sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE)))
__sock_recv_timestamp(msg, sk, skb);
else
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index b2df375..02c065f 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4212,7 +4212,7 @@ EXPORT_SYMBOL(skb_try_coalesce);
*/
void skb_scrub_packet(struct sk_buff *skb, bool xnet)
{
- skb->tstamp.tv64 = 0;
+ skb->tstamp = 0;
skb->pkt_type = PACKET_HOST;
skb->skb_iif = 0;
skb->ignore_df = 0;

View File

@ -1,11 +1,11 @@
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index b2a3220..18629c6 100644
index d4604bc..3f72629 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -2825,7 +2825,7 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue)
@@ -2798,7 +2798,7 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue)
txq = fep->tx_queue[queue];
bdp = txq->tx_bd_base;
for (i = 0; i < txq->tx_ring_size; i++) {
bdp = txq->bd.base;
for (i = 0; i < txq->bd.ring_size; i++) {
- txq->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL);
+ txq->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL | GFP_LX_DMA);
if (!txq->tx_bounce[i])

View File

@ -0,0 +1,3 @@
Device drivers needed for scenarios
using one network interface

View File

@ -0,0 +1,2 @@
_/src/fec_nic_drv
_/raw/drivers_nic-imx7d_sabre

View File

@ -0,0 +1 @@
2019-07-08 22eb1f5c9d136d343223df400af544eff2bad931

View File

@ -0,0 +1,4 @@
content: drivers.config
drivers.config:
cp $(REP_DIR)/recipes/raw/drivers_nic-imx7d_sabre/$@ $@

View File

@ -0,0 +1,31 @@
<config>
<parent-provides>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="ROM"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="Timer"/>
<service name="Gpio"/>
</parent-provides>
<default caps="100"/>
<service name="Nic">
<default-policy> <child name="nic_drv"/> </default-policy> </service>
<start name="nic_drv" caps="130">
<binary name="fec_nic_drv"/>
<resource name="RAM" quantum="20M"/>
<provides> <service name="Nic"/> </provides>
<config>
<!-- ENET1: IRQ 120 + 32 = 152 -->
<card type="fsl,imx6sx-fec" mii="rgmii" irq="152" mmio="0x30be0000"/>
<!-- ENET2: IRQ 102 + 32 = 134 -->
<card type="fsl,imx6sx-fec" mii="rgmii" irq="134" mmio="0x30bf0000"/>
</config>
<route> <any-service> <parent/> </any-service> </route>
</start>
</config>

View File

@ -0,0 +1 @@
2019-06-27 583a26eccfd3241f727170f5d9451c9f2d55d3b4

View File

@ -5,6 +5,16 @@
#include <linux/timecounter.h>
#include <net/tso.h>
void bus_unregister(struct bus_type *bus)
{
TRACE_AND_STOP;
}
void class_unregister(struct class *cls)
{
TRACE_AND_STOP;
}
size_t copy_from_user(void *to, void const *from, size_t len)
{
TRACE_AND_STOP;
@ -45,6 +55,11 @@ void dma_free_coherent(struct device * d, size_t size, void *vaddr, dma_addr_t b
TRACE_AND_STOP;
}
void driver_unregister(struct device_driver *drv)
{
TRACE_AND_STOP;
}
void dst_release(struct dst_entry *dst)
{
TRACE_AND_STOP;
@ -61,6 +76,17 @@ void eth_hw_addr_random(struct net_device *dev)
TRACE_AND_STOP;
}
void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, u32 legacy_u32)
{
TRACE_AND_STOP;
}
bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32,
const unsigned long *src)
{
TRACE_AND_STOP;
}
u32 ethtool_op_get_link(struct net_device * d)
{
TRACE_AND_STOP;
@ -89,12 +115,22 @@ void free_netdev(struct net_device * d)
TRACE_AND_STOP;
}
void free_uid(struct user_struct *dummy)
{
TRACE_AND_STOP;
}
bool gfp_pfmemalloc_allowed(gfp_t g)
{
TRACE_AND_STOP;
return -1;
}
bool gfpflags_allow_blocking(const gfp_t gfp_flags)
{
TRACE_AND_STOP;
}
int in_irq(void)
{
TRACE_AND_STOP;
@ -113,11 +149,31 @@ void *kmap_atomic(struct page *page)
return NULL;
}
const char *kobject_name(const struct kobject *kobj)
{
TRACE_AND_STOP;
}
void kunmap_atomic(void *addr)
{
TRACE_AND_STOP;
}
void might_sleep()
{
TRACE_AND_STOP;
}
void mm_unaccount_pinned_pages(struct mmpin *mmp)
{
TRACE_AND_STOP;
}
void module_put(struct module *mod)
{
TRACE_AND_STOP;
}
void netif_tx_disable(struct net_device *dev)
{
TRACE_AND_STOP;
@ -158,18 +214,53 @@ struct timespec64 ns_to_timespec64(const s64 nsec)
return ret;
}
int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
{
TRACE_AND_STOP;
}
int of_mdio_parse_addr(struct device *dev, const struct device_node *np)
{
TRACE_AND_STOP;
}
struct device_node *of_node_get(struct device_node *node)
{
TRACE_AND_STOP;
return NULL;
}
void of_phy_deregister_fixed_link(struct device_node *np)
{
TRACE_AND_STOP;
}
int of_phy_register_fixed_link(struct device_node *np)
{
TRACE_AND_STOP;
return -1;
}
bool of_property_read_bool(const struct device_node *np, const char *propname)
{
TRACE_AND_STOP;
}
void phy_led_triggers_unregister(struct phy_device *phy)
{
TRACE_AND_STOP;
}
void pm_runtime_disable(struct device *dev)
{
TRACE_AND_STOP;
}
int pm_runtime_put(struct device *dev)
{
TRACE_AND_STOP;
}
void ptp_clock_event(struct ptp_clock *ptp, struct ptp_clock_event *event)
{
TRACE_AND_STOP;
@ -187,12 +278,6 @@ int ptp_clock_unregister(struct ptp_clock *ptp)
return -1;
}
int regulator_disable(struct regulator *r)
{
TRACE_AND_STOP;
return -1;
}
bool page_is_pfmemalloc(struct page *page)
{
TRACE_AND_STOP;
@ -214,6 +299,52 @@ void read_unlock_bh(rwlock_t * l)
TRACE_AND_STOP;
}
int regulator_disable(struct regulator *r)
{
TRACE_AND_STOP;
return -1;
}
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
irq_handler_t thread_fn,
unsigned long flags, const char *name, void *dev)
{
TRACE_AND_STOP;
}
void sk_free(struct sock *sk)
{
TRACE_AND_STOP;
}
void sock_efree(struct sk_buff *skb)
{
TRACE_AND_STOP;
}
int strcmp(const char *s1, const char *s2)
{
TRACE_AND_STOP;
return -1;
}
char *strncpy(char *dst, const char *src, size_t s)
{
TRACE_AND_STOP;
}
int sysfs_create_link_nowarn(struct kobject *kobj,
struct kobject *target,
const char *name)
{
TRACE_AND_STOP;
}
void sysfs_remove_link(struct kobject *kobj, const char *name)
{
TRACE_AND_STOP;
}
unsigned int tcp_hdrlen(const struct sk_buff *skb)
{
TRACE_AND_STOP;
@ -252,42 +383,15 @@ void unregister_netdev(struct net_device * d)
TRACE_AND_STOP;
}
void usleep_range(unsigned long min, unsigned long max)
{
TRACE_AND_STOP;
}
void __vlan_hwaccel_put_tag(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
{
TRACE_AND_STOP;
}
void module_put(struct module *mod)
{
TRACE_AND_STOP;
}
void put_device(struct device *dev)
{
TRACE_AND_STOP;
}
int strcmp(const char *s1, const char *s2)
{
TRACE_AND_STOP;
return -1;
}
void class_unregister(struct class *cls)
{
TRACE_AND_STOP;
}
void bus_unregister(struct bus_type *bus)
{
TRACE_AND_STOP;
}
void driver_unregister(struct device_driver *drv)
{
TRACE_AND_STOP;
}
struct user_namespace init_user_ns;
int sysctl_tstamp_allow_data;

View File

@ -436,6 +436,7 @@ const struct of_device_id *of_match_device(const struct of_device_id *matches,
return nullptr;
}
void * devm_ioremap_resource(struct device *dev, struct resource *res)
{
Fec * fec = (Fec*) dev->plat_dev->dev.of_node;
@ -674,15 +675,15 @@ struct page *alloc_pages(gfp_t gfp_mask, unsigned int order)
}
void *__alloc_page_frag(struct page_frag_cache *, unsigned int const fragsz,
gfp_t const gfp_mask)
void *page_frag_alloc(struct page_frag_cache *, unsigned int const fragsz,
gfp_t const gfp_mask)
{
struct page *page = allocate_pages(gfp_mask, fragsz);
return page ? page->addr : page;
}
void __free_page_frag(void *addr)
void page_frag_free(void *addr)
{
struct page *page = Addr_to_page_mapping::remove((unsigned long)addr);
@ -693,6 +694,7 @@ void __free_page_frag(void *addr)
kfree(page);
}
int driver_register(struct device_driver *drv)
{
new (Lx::Malloc::mem()) Driver(drv);
@ -899,9 +901,10 @@ bool napi_schedule_prep(struct napi_struct *n)
}
void napi_complete(struct napi_struct *n)
bool napi_complete_done(struct napi_struct *n, int work_done)
{
clear_bit(NAPI_STATE_SCHED, &n->state);
return true;
}
@ -982,7 +985,7 @@ static int of_mdiobus_register_phy(Fec::Mdio::Phy & ph, struct mii_bus *mdio)
if (!phy || IS_ERR(phy)) return 1;
phy->irq = ph.gpio_irq;
phy->dev.of_node = (device_node*) &ph;
phy->mdio.dev.of_node = (device_node*) &ph;
/* All data is now stored in the phy struct;
* register it */
@ -1129,10 +1132,23 @@ u64 timecounter_read(struct timecounter *tc)
return nsec;
}
/*********************
** DUMMY FUNCTIONS **
*********************/
int bus_register(struct bus_type *bus)
{
TRACE;
return 0;
}
int class_register(struct class_ *cls)
{
TRACE;
return 0;
}
void clk_disable_unprepare(struct clk * c)
{
TRACE;
@ -1144,6 +1160,12 @@ int clk_prepare_enable(struct clk * c)
return 0;
}
int device_bind_driver(struct device *dev)
{
TRACE;
return 0;
}
void device_initialize(struct device *dev)
{
TRACE;
@ -1155,107 +1177,46 @@ int device_init_wakeup(struct device *dev, bool val)
return 0;
}
int device_set_wakeup_enable(struct device *dev, bool enable)
{
TRACE;
return 0;
}
struct regulator *__must_check devm_regulator_get(struct device *dev, const char *id)
{
TRACE;
return nullptr;
}
struct netdev_queue *netdev_get_tx_queue(const struct net_device *dev, unsigned int index)
{
TRACE;
return nullptr;
}
bool of_phy_is_fixed_link(struct device_node *np)
{
TRACE;
return 0;
}
int pinctrl_pm_select_default_state(struct device *dev)
{
TRACE;
return -1;
}
int pinctrl_pm_select_sleep_state(struct device *dev)
{
TRACE;
return -1;
}
struct resource *platform_get_resource(struct platform_device * d, unsigned r1, unsigned r2)
{
TRACE;
return nullptr;
}
void pm_runtime_enable(struct device *dev)
void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr, size_t size,
enum dma_data_direction dir)
{
TRACE;
}
void pm_runtime_get_noresume(struct device *dev)
void dma_sync_single_for_device(struct device *dev, dma_addr_t addr,
size_t size, enum dma_data_direction dir)
{
TRACE;
}
int pm_runtime_set_active(struct device *dev)
{
TRACE;
return 0;
}
void pm_runtime_set_autosuspend_delay(struct device *dev, int delay)
{
TRACE;
}
void pm_runtime_use_autosuspend(struct device *dev)
{
TRACE;
}
struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info, struct device *parent)
{
TRACE;
return (ptp_clock*)0xdeadbeef;
}
int regulator_enable(struct regulator * d)
{
TRACE;
return 0;
}
int class_register(struct class_ *cls)
{
TRACE;
return 0;
}
int try_module_get(struct module *mod)
{
TRACE;
return -1;
}
struct device *get_device(struct device *dev)
{
TRACE;
return dev;
}
int device_bind_driver(struct device *dev)
struct netdev_queue *netdev_get_tx_queue(const struct net_device *dev, unsigned int index)
{
TRACE;
return 0;
return nullptr;
}
void netif_tx_start_all_queues(struct net_device *dev)
bool netdev_uses_dsa(struct net_device *dev)
{
TRACE;
return false;
}
void netif_tx_lock_bh(struct net_device *dev)
@ -1263,18 +1224,7 @@ void netif_tx_lock_bh(struct net_device *dev)
TRACE;
}
int device_set_wakeup_enable(struct device *dev, bool enable)
{
TRACE;
return 0;
}
void trace_consume_skb(struct sk_buff * sb)
{
TRACE;
}
void trace_kfree_skb(struct sk_buff * sb, void * p)
void netif_tx_start_all_queues(struct net_device *dev)
{
TRACE;
}
@ -1289,22 +1239,17 @@ void netif_wake_queue(struct net_device * d)
TRACE;
}
bool netdev_uses_dsa(struct net_device *dev)
const void *of_get_mac_address(struct device_node *np)
{
TRACE;
return false;
return nullptr;
}
void dma_sync_single_for_device(struct device *dev, dma_addr_t addr,
size_t size, enum dma_data_direction dir)
{
TRACE;
}
int of_machine_is_compatible(const char *compat)
void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr, size_t size,
enum dma_data_direction dir)
{
TRACE;
return 0;
}
void of_node_put(struct device_node *node)
@ -1312,12 +1257,102 @@ void of_node_put(struct device_node *node)
TRACE;
}
const void *of_get_mac_address(struct device_node *np)
bool of_phy_is_fixed_link(struct device_node *np)
{
TRACE;
return 0;
}
void phy_led_trigger_change_speed(struct phy_device *phy)
{
TRACE;
}
int phy_led_triggers_register(struct phy_device *phy)
{
TRACE;
return -1;
}
int pinctrl_pm_select_default_state(struct device *dev)
{
TRACE;
return -1;
}
int pinctrl_pm_select_sleep_state(struct device *dev)
{
TRACE;
return -1;
}
int platform_get_irq_byname(struct platform_device *dev, const char *name)
{
TRACE;
return -1;
}
struct resource *platform_get_resource(struct platform_device * d, unsigned r1, unsigned r2)
{
TRACE;
return nullptr;
}
int platform_irq_count(struct platform_device *dev)
{
TRACE;
return 0;
}
void pm_runtime_enable(struct device *dev)
{
TRACE;
}
void pm_runtime_get_noresume(struct device *dev)
{
TRACE;
}
int pm_runtime_set_active(struct device *dev)
{
TRACE;
return 0;
}
void pm_runtime_use_autosuspend(struct device *dev)
{
TRACE;
}
void pm_runtime_set_autosuspend_delay(struct device *dev, int delay)
{
TRACE;
}
struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info, struct device *parent)
{
TRACE;
return (ptp_clock*)0xdeadbeef;
}
void put_device(struct device *dev)
{
TRACE;
}
int regulator_enable(struct regulator * d)
{
TRACE;
return 0;
}
int request_module(const char *fmt, ...)
{
TRACE;
return 0;
}
void rtnl_lock(void)
{
TRACE;
@ -1328,16 +1363,36 @@ void rtnl_unlock(void)
TRACE;
}
int request_module(const char *fmt, ...)
void secpath_reset(struct sk_buff *skb)
{
TRACE;
return 0;
}
int bus_register(struct bus_type *bus)
int sysfs_create_link(struct kobject *kobj, struct kobject *target, const char *name)
{
TRACE;
return 0;
return -1;
}
void trace_consume_skb(struct sk_buff * sb)
{
TRACE;
}
void trace_kfree_skb(struct sk_buff * sb, void * p)
{
TRACE;
}
void trace_mdio_access(void *dummy, ...)
{
TRACE;
}
int try_module_get(struct module *mod)
{
TRACE;
return -1;
}
}

View File

@ -19,10 +19,43 @@
#include <lx_emul/extern_c_begin.h>
#include <lx_emul/barrier.h>
#include <lx_emul/compiler.h>
#include <lx_emul/printf.h>
#include <lx_emul/types.h>
static inline void __read_once_size(const volatile void *p, void *res, int size)
{
switch (size) {
case 1: *(__u8 *)res = *(volatile __u8 *)p; break;
case 2: *(__u16 *)res = *(volatile __u16 *)p; break;
case 4: *(__u32 *)res = *(volatile __u32 *)p; break;
case 8: *(__u64 *)res = *(volatile __u64 *)p; break;
default:
barrier();
__builtin_memcpy((void *)res, (const void *)p, size);
barrier();
}
}
#ifdef __cplusplus
#define READ_ONCE(x) \
({ \
barrier(); \
x; \
})
#else
#define READ_ONCE(x) \
({ \
union { typeof(x) __val; char __c[1]; } __u; \
__read_once_size(&(x), __u.__c, sizeof(x)); \
__u.__val; \
})
#endif
#include <lx_emul/list.h>
void lx_backtrace(void);
#define DEBUG_LINUX_PRINTK 0
@ -59,8 +92,6 @@ typedef int clockid_t;
enum { PAGE_SHIFT = 12 };
enum { HZ = 100UL, };
struct list_head;
typedef __u16 __le16;
typedef __u32 __le32;
typedef __u64 __le64;
@ -129,7 +160,6 @@ enum {
__GFP_REPEAT = 0x00000400u,
};
#include <lx_emul/barrier.h>
#include <uapi/linux/swab.h>
#include <lx_emul/byteorder.h>
#include <lx_emul/completion.h>
@ -138,6 +168,7 @@ enum {
#include <uapi/linux/ptp_clock.h>
#include <lx_emul/pm.h>
#include <lx_emul/scatterlist.h>
#include <lx_emul/kobject.h>
enum {
ETH_HLEN = 14,
@ -206,11 +237,6 @@ static inline s64 timespec64_to_ns(const struct timespec64 *ts)
ktime_t ns_to_ktime(u64 ns);
struct device_node
{
const char * full_name;
};
struct device;
struct device_driver;
@ -220,6 +246,7 @@ struct bus_type
const struct attribute_group **dev_groups;
int (*match)(struct device *dev, struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
int (*probe)(struct device *dev);
const struct dev_pm_ops *pm;
@ -255,6 +282,7 @@ struct platform_device;
struct device {
char name[32];
struct device * parent;
struct kobject kobj;
struct device_driver *driver;
void * platform_data;
void * driver_data;
@ -263,7 +291,8 @@ struct device {
struct bus_type *bus;
struct class *class;
struct device_node *of_node;
struct platform_device * plat_dev;
struct fwnode_handle *fwnode;
struct platform_device *plat_dev;
};
struct platform_device {
@ -358,6 +387,7 @@ struct net_device
netdev_features_t features;
struct net_device_stats stats;
netdev_features_t hw_features;
int ifindex;
const struct net_device_ops *netdev_ops;
const struct ethtool_ops *ethtool_ops;
const struct header_ops *header_ops;
@ -365,7 +395,10 @@ struct net_device
unsigned int priv_flags;
unsigned short hard_header_len;
unsigned long mtu;
unsigned int min_mtu;
unsigned long max_mtu;
unsigned short type;
unsigned char min_header_len;
unsigned char addr_len;
struct netdev_hw_addr_list mc;
unsigned char *dev_addr;
@ -373,7 +406,7 @@ struct net_device
unsigned long tx_queue_len;
int watchdog_timeo;
struct timer_list watchdog_timer;
struct device dev;
struct device dev;
u16 gso_max_segs;
struct phy_device *phydev;
};
@ -427,8 +460,6 @@ static inline int rcu_read_lock_bh_held(void) { return 1; }
unsigned int jiffies_to_usecs(const unsigned long j);
struct rb_node {};
#define __aligned(x) __attribute__((aligned(x)))
#define kmemcheck_bitfield_begin(name)
@ -602,7 +633,10 @@ bool netif_queue_stopped(const struct net_device *dev);
#define CONFIG_ARM 1
#define CONFIG_ARCH_MXC 1
#define CONFIG_DEBUG_LOCK_ALLOC 1
#define CONFIG_MDIO_DEVICE 1
#define CONFIG_OF_MDIO 1
#define CONFIG_PHYLIB 1
#define CONFIG_PTP_1588_CLOCK 1
void rtnl_lock(void);
@ -617,26 +651,7 @@ void netif_tx_unlock_bh(struct net_device *dev);
void napi_enable(struct napi_struct *n);
void napi_disable(struct napi_struct *n);
static inline void __read_once_size(const volatile void *p, void *res, int size)
{
switch (size) {
case 1: *(__u8 *)res = *(volatile __u8 *)p; break;
case 2: *(__u16 *)res = *(volatile __u16 *)p; break;
case 4: *(__u32 *)res = *(volatile __u32 *)p; break;
case 8: *(__u64 *)res = *(volatile __u64 *)p; break;
default:
barrier();
__builtin_memcpy((void *)res, (const void *)p, size);
barrier();
}
}
#define READ_ONCE(x) \
({ \
union { typeof(x) __val; char __c[1]; } __u; \
__read_once_size(&(x), __u.__c, sizeof(x)); \
__u.__val; \
})
#define __randomize_layout
extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
size, unsigned long offset);
@ -669,12 +684,6 @@ gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb);
void dma_sync_single_for_device(struct device *dev, dma_addr_t addr, size_t size, enum dma_data_direction dir);
bool napi_schedule_prep(struct napi_struct *n);
void __napi_schedule(struct napi_struct *n);
void napi_complete(struct napi_struct *n);
void *dev_get_platdata(const struct device *dev);
int is_valid_ether_addr(const u8 *);
@ -710,6 +719,473 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np);
struct resource *platform_get_resource(struct platform_device *, unsigned, unsigned);
/*******************************
** asm-generic/atomic-long.h **
*******************************/
static inline int atomic_long_cmpxchg(atomic_long_t *v, long old, long n) {
return cmpxchg(&v->counter, old, n); }
/************************
** linux/capability.h **
************************/
bool capable(int);
/*************************
** linux/cgroup-defs.h **
*************************/
struct cgroup;
/******************
** linux/cred.h **
******************/
struct user_struct *current_user();
/*******************
** linux/delay.h **
*******************/
void usleep_range(unsigned long min, unsigned long max);
/*************************
** linux/etherdevice.h **
*************************/
static inline void ether_addr_copy(u8 *dst, const u8 *src)
{
*(u32 *)dst = *(const u32 *)src;
*(u16 *)(dst+ 4) = *(const u16 *)(src + 4);
}
/*********************
** linux/ethtool.h **
*********************/
struct ethtool_link_ksettings;
/****************
** linux/fs.h **
****************/
typedef struct {
size_t written;
size_t count;
union {
char __user *buf;
void *data;
} arg;
int error;
} read_descriptor_t;
/********************
** linux/fwnode.h **
********************/
struct fwnode_handle { int dummy; };
/**********************
** linux/mm_types.h **
**********************/
struct page_frag_cache
{
bool pfmemalloc;
};
/*****************
** linux/gfp.h **
*****************/
void *page_frag_alloc(struct page_frag_cache *nc,
unsigned int fragsz, gfp_t gfp_mask);
void page_frag_free(void *addr);
/*********************
** linux/if_vlan.h **
*********************/
static inline bool eth_type_vlan(__be16 ethertype) { return false; }
/***********************
** linux/interrupt.h **
***********************/
#define IRQF_SHARED 0x00000080
#define IRQF_ONESHOT 0x00002000
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
irq_handler_t thread_fn,
unsigned long flags, const char *name, void *dev);
/*********************
** linux/lockdep.h **
*********************/
struct lockdep_map { };
#define mutex_release(l, n, i)
/*****************************
** linux/mod_devicetable.h **
*****************************/
#define MDIO_NAME_SIZE 32
/************************
** linux/memcontrol.h **
************************/
struct mem_cgroup;
#define mem_cgroup_sockets_enabled 0
static inline bool mem_cgroup_under_socket_pressure(struct mem_cgroup *memcg) {
return false; }
/***********************
** linux/netdevice.h **
***********************/
void __napi_schedule(struct napi_struct *n);
typedef struct sk_buff **(*gro_receive_t)(struct sk_buff **, struct sk_buff *);
struct sk_buff **call_gro_receive(gro_receive_t cb, struct sk_buff **head, struct sk_buff *skb);
void dev_consume_skb_any(struct sk_buff *skb);
bool napi_complete_done(struct napi_struct *n, int work_done);
bool napi_schedule_prep(struct napi_struct *n);
void skb_gro_flush_final(struct sk_buff *skb, struct sk_buff **pp, int flush);
/****************
** linux/of.h **
****************/
struct device_node
{
const char * full_name;
struct fwnode_handle fwnode;
};
#define of_fwnode_handle(node) \
({ \
typeof(node) __of_fwnode_handle_node = (node); \
\
__of_fwnode_handle_node ? \
&__of_fwnode_handle_node->fwnode : NULL; \
})
int of_machine_is_compatible(const char *compat);
bool of_property_read_bool(const struct device_node *np, const char *propname);
/***********************
** linux/of_device.h **
***********************/
int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env);
/*********************
** linux/of_mdio.h **
*********************/
int of_mdio_parse_addr(struct device *dev, const struct device_node *np);
void of_phy_deregister_fixed_link(struct device_node *np);
/*****************
** linux/pci.h **
*****************/
int dev_is_pci(struct device *dev);
struct pci_dev;
struct device_node * pci_device_to_OF_node(const struct pci_dev *pdev);
#define to_pci_dev(n) NULL
/******************************
** linux/phy_led_triggers.h **
******************************/
void phy_led_trigger_change_speed(struct phy_device *phy);
int phy_led_triggers_register(struct phy_device *phy);
void phy_led_triggers_unregister(struct phy_device *phy);
/*****************************
** linux/platform_device.h **
*****************************/
int platform_get_irq_byname(struct platform_device *dev, const char *name);
int platform_irq_count(struct platform_device *);
/************************
** linux/pm_runtime.h **
************************/
void pm_runtime_disable(struct device *dev);
int pm_runtime_put(struct device *dev);
/*********************
** linux/preempt.h **
*********************/
#define in_task() (1)
/**********************
** linux/rcupdate.h **
**********************/
#define rcu_assign_pointer(p, v) (p = v);
#define rcu_dereference_protected(p, c) p
/*************************
** linux/scatterlist.h **
*************************/
#define sg_is_last(sg) ((sg)->page_link & 0x02)
/**************************
** linux/sched/signal.h **
**************************/
unsigned long rlimit(unsigned int limit);
/************************
** linux/sched/user.h **
************************/
struct user_struct
{
atomic_long_t locked_vm;
};
void free_uid(struct user_struct *);
struct user_struct *get_uid(struct user_struct *u);
/******************
** linux/sctp.h **
******************/
struct sctphdr
{
unsigned unused;
};
struct kmem_cache *kmem_cache_create_usercopy(const char *name, size_t size,
size_t align, slab_flags_t flags,
size_t useroffset, size_t usersize,
void (*ctor)(void *));
/******************
** linux/slab.h **
******************/
void *kcalloc(size_t n, size_t size, gfp_t flags);
void kmem_cache_free_bulk(struct kmem_cache *, size_t, void **);
/**********************
** linux/spinlock.h **
**********************/
int spin_is_locked(spinlock_t *lock);
/********************
** linux/stddef.h **
********************/
#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))
/*******************
** linux/sysfs.h **
*******************/
int sysfs_create_link(struct kobject *kobj, struct kobject *target, const char *name);
int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target, const char *name);
void sysfs_remove_link(struct kobject *kobj, const char *name);
/*************************
** linux/thread_info.h **
*************************/
static inline void check_object_size(const void *ptr, unsigned long n,
bool to_user) { }
void __bad_copy_from(void);
void __bad_copy_to(void);
static inline void copy_overflow(int size, unsigned long count)
{
WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count);
}
static __always_inline bool
check_copy_size(const void *addr, size_t bytes, bool is_source)
{
int sz = __compiletime_object_size(addr);
if (unlikely(sz >= 0 && sz < bytes)) {
if (!__builtin_constant_p(bytes))
copy_overflow(sz, bytes);
else if (is_source)
__bad_copy_from();
else
__bad_copy_to();
return false;
}
check_object_size(addr, bytes, is_source);
return true;
}
/****************************
** linux/user_namespace.h **
****************************/
struct user_namespace { };
/********************
** linux/uidgid.h **
********************/
kuid_t make_kuid(struct user_namespace *from, uid_t uid);
/*****************
** linux/uio.h **
*****************/
struct kvec
{
void *iov_base;
size_t iov_len;
};
bool _copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i);
static __always_inline __must_check
bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i)
{
if (unlikely(!check_copy_size(addr, bytes, false)))
return false;
else
return _copy_from_iter_full(addr, bytes, i);
}
bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i);
bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i);
/******************
** linux/wait.h **
******************/
bool wq_has_sleeper(struct wait_queue_head *wq_head);
/********************
** net/checksum.h **
********************/
static inline __wsum
csum_block_sub(__wsum csum, __wsum csum2, int offset)
{
return csum_block_add(csum, ~csum2, offset);
}
static inline __wsum csum_unfold(__sum16 n)
{
return (__force __wsum)n;
}
/**************************
** net/flow_dissector.h **
**************************/
#define FLOW_DISSECTOR_F_PARSE_1ST_FRAG BIT(0)
/*************************
** net/net_namespace.h **
*************************/
struct net;
/******************
** net/l3mdev.h **
******************/
int l3mdev_master_ifindex_by_index(struct net *net, int ifindex);
/*********************
** net/pkt_sched.h **
*********************/
#define DEFAULT_TX_QUEUE_LEN 1000
/***********************
** soc/imx/cpuidle.h **
***********************/
static inline void imx6q_cpuidle_fec_irqs_used(void) { }
static inline void imx6q_cpuidle_fec_irqs_unused(void) { }
/*************************
** trace/events/mdio.h **
*************************/
void trace_mdio_access(void *dummy, ...);
/*********************************
** uapi/asm-generic/resource.h **
*********************************/
# define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */
/*****************************
** uapi/linux/capability.h **
*****************************/
#define CAP_IPC_LOCK 14
/*************************
** uapi/linux/kernel.h **
*************************/
#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
/******************************
** uapi/linux/libc-compat.h **
******************************/
#define __UAPI_DEF_IF_IFMAP 1
#define __UAPI_DEF_IF_IFNAMSIZ 1
#define __UAPI_DEF_IF_IFREQ 1
#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1
/************************
** uapi/linux/types.h **
************************/
typedef unsigned __poll_t;
/************************/
#define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]
#include <uapi/linux/if_ether.h>
#include <uapi/linux/if_packet.h>
#include <uapi/linux/ethtool.h>
@ -727,30 +1203,6 @@ bool device_may_wakeup(struct device *dev);
int enable_irq_wake(unsigned int irq);
int disable_irq_wake(unsigned int irq);
struct ethtool_ops {
int(*get_settings)(struct net_device *, struct ethtool_cmd *);
int(*set_settings)(struct net_device *, struct ethtool_cmd *);
void(*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *);
int(*get_regs_len)(struct net_device *);
void(*get_regs)(struct net_device *, struct ethtool_regs *, void *);
void(*get_wol)(struct net_device *, struct ethtool_wolinfo *);
int(*set_wol)(struct net_device *, struct ethtool_wolinfo *);
int(*nway_reset)(struct net_device *);
u32(*get_link)(struct net_device *);
int(*get_coalesce)(struct net_device *, struct ethtool_coalesce *);
int(*set_coalesce)(struct net_device *, struct ethtool_coalesce *);
void(*get_pauseparam)(struct net_device *, struct ethtool_pauseparam*);
int(*set_pauseparam)(struct net_device *, struct ethtool_pauseparam*);
void(*get_strings)(struct net_device *, u32 stringset, u8 *);
void(*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, u64 *);
int(*get_sset_count)(struct net_device *, int);
int(*get_ts_info)(struct net_device *, struct ethtool_ts_info *);
int(*get_tunable)(struct net_device *,
const struct ethtool_tunable *, void *);
int(*set_tunable)(struct net_device *,
const struct ethtool_tunable *, const void *);
};
u32 ethtool_op_get_link(struct net_device *);
void *dma_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t);
@ -764,10 +1216,6 @@ int pinctrl_pm_select_sleep_state(struct device *dev);
void netif_tx_disable(struct net_device *dev);
#include <lx_emul/list.h>
#define rcu_assign_pointer(p, v) (p = v);
#include <linux/rculist.h>
#define netdev_hw_addr_list_for_each(ha, l) \
@ -899,8 +1347,6 @@ typedef int rwlock_t;
bool gfp_pfmemalloc_allowed(gfp_t);
struct user_namespace {};
struct cred {
struct user_namespace * user_ns;
};
@ -909,7 +1355,10 @@ struct file {
const struct cred * f_cred;
};
struct net;
struct net
{
struct user_namespace * user_ns;
};
struct percpu_counter {
s64 count;
@ -975,9 +1424,6 @@ struct net *dev_net(const struct net_device *dev);
#define read_pnet(pnet) (&init_net)
#define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]
void bitmap_fill(unsigned long *dst, int nbits);
void bitmap_zero(unsigned long *dst, int nbits);
@ -1041,7 +1487,10 @@ void page_counter_uncharge(struct page_counter *counter, unsigned long nr_pages)
enum { UNDER_LIMIT, SOFT_LIMIT, OVER_LIMIT };
struct inode {};
struct inode
{
kuid_t i_uid;
};
struct vm_area_struct;
@ -1097,11 +1546,6 @@ struct page *virt_to_head_page(const void *x);
typeof(type) name
#define this_cpu_ptr(ptr) ptr
struct page_frag_cache
{
bool pfmemalloc;
};
void *__alloc_page_frag(struct page_frag_cache *nc, unsigned int fragsz, gfp_t gfp_mask);
unsigned long local_irq_save(unsigned long flags);
@ -1170,7 +1614,10 @@ void sg_mark_end(struct scatterlist *sg);
void sg_set_buf(struct scatterlist *, const void *, unsigned int);
void sg_set_page(struct scatterlist *, struct page *, unsigned int, unsigned int);
struct inet_skb_parm { };
struct inet_skb_parm
{
int iif;
};
enum {
IPPROTO_IP = 0,
@ -1374,10 +1821,6 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
for (child = of_get_next_available_child(parent, NULL); child != NULL; \
child = of_get_next_available_child(parent, child))
u32 mmd_eee_cap_to_ethtool_sup_t(u16 eee_cap);
u32 mmd_eee_adv_to_ethtool_adv_t(u16 eee_adv);
u16 ethtool_adv_to_mmd_eee_adv_t(u32 adv);
int driver_register(struct device_driver *drv);
void driver_unregister(struct device_driver *drv);
@ -1401,9 +1844,10 @@ static inline bool is_multicast_ether_addr_64bits(const u8 addr[6+2])
static inline bool ether_addr_equal_64bits(const u8 addr1[6+2], const u8 addr2[6+2])
{
u64 fold = (*(const u64 *)addr1) ^ (*(const u64 *)addr2);
const u16 *a = (const u16 *)addr1;
const u16 *b = (const u16 *)addr2;
return (fold << 16) == 0;
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0;
}
static inline bool eth_proto_is_802_3(__be16 proto)
@ -1483,6 +1927,7 @@ void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp);
struct pm_qos_request {};
#define dma_wmb() __asm__ __volatile__ ("dmb oshst" : : : "memory")
#include <lx_emul/extern_c_end.h>
#endif /* _SRC__DRIVERS__NIC__FEC__LX_EMUL_H_ */

View File

@ -29,16 +29,17 @@ CC_C_OPT += -std=gnu89
#
# Reduce build noise of compiling contrib code
#
CC_OPT_fec_ptp = -Wno-unused-but-set-variable -Wno-unused-variable \
-Wno-maybe-uninitialized -Wno-uninitialized
CC_OPT_fec_main = -Wno-unused-but-set-variable -Wno-unused-variable \
-Wno-pointer-sign -Wno-int-conversion -Wno-unused-function \
-Wno-uninitialized
CC_OPT_skbuff = -Wno-pointer-sign -Wno-int-conversion -Wno-uninitialized
CC_OPT_mdio_bus = -Wno-implicit-int -Wno-unused-function -Wno-pointer-sign
CC_OPT_eth = -Wno-pointer-sign -Wno-unused-function
CC_OPT_phy = -Wno-unused-function -Wno-unused-but-set-variable
CC_OPT_at803x = -Wno-unused-variable
CC_OPT_fec_ptp = -Wno-unused-but-set-variable -Wno-unused-variable \
-Wno-maybe-uninitialized -Wno-uninitialized
CC_OPT_fec_main = -Wno-unused-but-set-variable -Wno-unused-variable \
-Wno-pointer-sign -Wno-int-conversion -Wno-unused-function \
-Wno-uninitialized
CC_OPT_skbuff = -Wno-pointer-sign -Wno-int-conversion -Wno-uninitialized
CC_OPT_mdio_bus = -Wno-implicit-int -Wno-unused-function -Wno-pointer-sign
CC_OPT_eth = -Wno-pointer-sign -Wno-unused-function
CC_OPT_phy = -Wno-unused-function -Wno-unused-but-set-variable
CC_OPT_phy_device = -Wno-unused-function
CC_OPT_at803x = -Wno-unused-variable
vpath %.c $(LX_CONTRIB_DIR)/drivers/net/ethernet/freescale
vpath %.c $(LX_CONTRIB_DIR)/drivers/net/phy

View File

@ -258,7 +258,7 @@ int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
*********************/
int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) { TRACE; return 0; }
char *kobject_name(const struct kobject *kobj) { TRACE; return 0; }
const char *kobject_name(const struct kobject *kobj) { TRACE; return 0; }
char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask) { TRACE; return 0; }

View File

@ -231,7 +231,7 @@ int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
*********************/
int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) { TRACE; return 0; }
char *kobject_name(const struct kobject *kobj) { TRACE; return 0; }
const char *kobject_name(const struct kobject *kobj) { TRACE; return 0; }
char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask) { TRACE; return 0; }

View File

@ -70,6 +70,10 @@
#define smp_read_barrier_depends() do { } while (0)
#define smp_store_mb(var, value) do { WRITE_ONCE(var, value); barrier(); } while (0)
#ifndef __compiletime_object_size
# define __compiletime_object_size(obj) -1
#endif
/**************************
** linux/compiler-gcc.h **
**************************/
@ -78,6 +82,8 @@
#define __packed __attribute__((packed))
#endif
#define __weak __attribute__((weak))
#define __aligned(x) __attribute__((aligned(x)))
#define uninitialized_var(x) x = x

View File

@ -26,6 +26,7 @@
#define __is_defined(x) ___is_defined(x)
#define IS_BUILTIN(option) __is_defined(option)
#define IS_ENABLED(option) IS_BUILTIN(option)
#define IS_REACHABLE(option) IS_BUILTIN(option)
/********************
** linux/kernel.h **

View File

@ -52,6 +52,6 @@ struct kobj_uevent_env;
int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...);
void kobject_put(struct kobject *);
char *kobject_name(const struct kobject *kobj);
const char *kobject_name(const struct kobject *kobj);
char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask);
struct kobject * kobject_create_and_add(const char *, struct kobject *);

View File

@ -0,0 +1,5 @@
SRC_CC = vfs.cc
vpath %.cc $(REP_DIR)/src/lib/vfs/trace
SHARED_LIB = yes

View File

@ -1,8 +1,15 @@
<runtime ram="40M" caps="1000" binary="init" config="wm.config">
<requires> <nitpicker/> <timer/> </requires>
<requires>
<nitpicker label="focus"/>
<nitpicker/>
<report label="shape"/>
<report label="clipboard"/>
<rom label="clipboard"/>
<timer/>
</requires>
<provides> <nitpicker/> </provides>
<provides> <nitpicker/> <report/> <rom/> </provides>
<content>
<rom label="ld.lib.so"/>

View File

@ -1,8 +1,8 @@
=====================================
Sculpt as a community experience (CE)
=====================================
=============================
Sculpt Operating System 19.07
=============================
Norman Feske
@ -58,13 +58,13 @@ Your feedback is appreciated!
[https://www.genode-labs.com]
A printable PDF version of this document is available at
[https://genode.org/documentation/sculpt-ce.pdf].
[https://genode.org/documentation/sculpt-19-07.pdf].
Hardware requirements and preparations
######################################
Sculpt CE should be compatible with recent Intel-based PC hardware featuring
Sculpt should be compatible with recent Intel-based PC hardware featuring
Intel graphics, E1000 networking, Intel wireless, and AHCI/NVMe.
It is tested best on laptops of the Lenovo X and T series (X220, X250, X260,
@ -185,16 +185,21 @@ information along with the option to remove it from the system.
As a next step, let us add a window system. In the '+' menu, you can find
a readily packaged window system at _genodelabs_ -> _GUI_ -> _themed wm_.
After installing the package, you are asked to take three decisions:
After installing the package, you are asked to take five decisions:
The _GUI (focus)_ should be assigned to "keyboard focus" to put the
window manager in charge of controlling the keyboard focus, which is part
of its job after all.
The _GUI_ should be assigned to "system GUI server" as the basic mechanism
to be used for graphical output and user input for the windowed applications.
Finally, by assigning _Report_ to _system reports_, we allow the window
By assigning _Report (shape)_ to _pointer shape_, we allow the window
manager to report information about mouse-pointer shapes.
By adding the component, the "themed wm" will appear in the runtime view.
By assigning _Report (clipboard)_ to _global clipboard_, we grant the
window manager the right to change the content of the global clipboard.
Vice versa, by assigning _ROM (clipboard)_, we permit the window manager
to obtain clipboard content.
After adding the component, the "themed wm" will appear in the runtime view.
To give the window system a quick try, add the small demo you can find at
_genodelabs_ -> _Demos_ -> _nano3d_ and assign its _GUI_ to our "themed wm".
@ -238,6 +243,14 @@ dialog is a bit more elaborate this time.
within the instance. Select "default vim configuration" to grant
read-only access to this information.
:ROM (clipboard): defines the service to obtain clipboard content from.
Select "themed wm" (not "global clipboard").
:Report (clipboard): defines the service for reporting new clipboard content.
Select "themed wm". More information about the integration and use of the
clipboard can be found in
[https://genodians.org/nfeske/2019-07-03-copy-paste - a dedicated article].
With those decisions taken, a fresh noux runtime can be started, which appears
in a window.
@ -261,6 +274,13 @@ Of course, there are many more components to explore and to combine.
For inspiration, please follow the postings at
[https://genodians.org], for example:
:Copy and paste mechanism:
Sculpt provides a built-in mechanism for exchanging data between
virtual machines, terminals, and Qt applications:
[https://genodians.org/nfeske/2019-07-03-copy-paste]
:Use GNU/Linux inside a virtual machine on top of Sculpt:
There is a ready-to-use package for downloading Debian for the use inside
@ -440,9 +460,9 @@ the running system using a command-line interface and the Vim text editor.
Vim skills recommended
----------------------
Sculpt CE leverages (a subset of) GNU coreutils, bash, and Vim as the user
Sculpt leverages (a subset of) GNU coreutils, bash, and Vim as the user
interface for sculpting the system. If you are not yet familiar with using
Vim, you may take Sculpt CE as a welcome chance to get your toes wet. To
Vim, you may take Sculpt as a welcome chance to get your toes wet. To
enjoy the experience, you should be comfortable with the following
operations:
@ -586,8 +606,14 @@ as options.
| | platform information
----------------------------------------------------------------------------
| | system status
----------------------------------------------------------------------------
| | global clipboard
----------------------------------------------------------------------------
Report | 'Report' | system reports
----------------------------------------------------------------------------
| | pointer shape
----------------------------------------------------------------------------
| | global clipboard
----------------------------------------------------------------------------
File system | 'File_system' | writeable system configuration
----------------------------------------------------------------------------
@ -708,6 +734,11 @@ the following built-in ROM resources:
optional ACPICA driver to respond to requests for a system reset or
power-down.
:global clipboard: provides the current content of the global clipboard.
The content can be accessed by a component only when the user interacts
with the component. This prevents overly nosey components from snooping the
clipboard content.
Report
~~~~~~
@ -723,10 +754,16 @@ keep in mind that Sculpt's built-in report file system is limited in size.
A misbehaving component may put the system in jeopardy by producing overly
sized reports.
Reports labeled with 'shape' play a special role. They are routed to the mouse
pointer and thereby enable graphical applications to suggest context-specific
pointer shapes. The application-provided shape is shown whenever the
corresponding application is hovered.
:pointer shape: Reports labeled with 'shape' play a special role.
They are routed to the mouse pointer and thereby enable graphical
applications to suggest context-specific pointer shapes. The
application-provided shape is shown whenever the corresponding application
is hovered.
:global clipboard: enables components to write new content to the
system-global clipboard. This operation, however, is restricted to the
single component that the user currently interacts with. This prevents
rogue components from spamming the global clipboard.
File system
@ -1123,26 +1160,26 @@ a free download at [https://genode.org].
# Download the support for the NOVA microkernel
! ./tool/depot/download genodelabs/bin/x86_64/base-nova/2019-03-17
! ./tool/depot/download genodelabs/bin/x86_64/base-nova/2019-07-08
The content is downloaded to the _public/_ directory and extracted to
the _depot/_ directory.
# Download all ingredients for the Sculpt boot image
! ./tool/depot/download genodelabs/pkg/x86_64/sculpt/2019-03-19
! ./tool/depot/download genodelabs/pkg/x86_64/sculpt/2019-07-08
# Create a build directory
! ./tool/create_builddir x86_64
# Configure the build directory by editing _build/x86_64/etc/build.conf_.
Most importantly, enable the 'gems' source-code repository where the
Sculpt scenario resides. In addition, the 'ports', 'dde_linux' and 'dde_ipxe'
repository are needed as well. Second, change the default configuration
of the 'QEMU_RUN_OPT' variable to 'image/disk' instead of 'image/iso'.
This way, the build process will produce a valid disk image with a GPT
partition table instead of a legacy ISO image.
Most importantly, enable the 'gems' source-code repository where the Sculpt
scenario resides. In addition, the 'libports', 'ports', 'dde_linux' and
'dde_ipxe' repository are needed as well. Second, change the default
configuration of the 'QEMU_RUN_OPT' variable to 'image/disk' instead of
'image/iso'. This way, the build process will produce a valid disk image
with a GPT partition table instead of a legacy ISO image.
# Create the Sculpt boot image (defined by the run script at
_repos/gems/run/sculpt.run_)
@ -1170,12 +1207,13 @@ Before building the packages, various ports of 3rd-party software need to
be prepared. The following command prepares all of them at once:
! <GENODE-DIR>/tool/ports/prepare_port \
! bash coreutils curl dde_ipxe dde_linux \
! dde_rump e2fsprogs gnupg grub2 jitterentropy \
! libarchive libc libgcrypt libiconv libssh \
! lwip_legacy ncurses nova openssl qemu-usb \
! stdcxx vim virtualbox5 x86emu xz zlib libpng \
! ttf-bitstream-vera stb
! acpica bash coreutils curl dde_ipxe dde_linux \
! dde_rump drm e2fsprogs expat freetype gnupg \
! jitterentropy jpeg libarchive libc libgcrypt \
! libiconv libpng libssh mesa ncurses nova openssl \
! pcre qemu-usb qoost qt5 stb stdcxx \
! ttf-bitstream-vera vim virtualbox5 x86emu xz \
! zlib
The ingredients of the boot image are subsumed by the 'pkg/sculpt' package.
The default set of software installed by the update runtime is defined by
@ -1208,6 +1246,14 @@ to those that do not yet exist in binary form. If not specified, the
command would recompile all packages each time. You may further add '-j<N>'
to parallelize the build process where '<N>' is the level of parallelism.
Alternatively to managing the depot manually, you may choose to let the build
system manage the versioning and updating of the depot content automatically
by enabling the following line in your _build.conf_ file. This slows down
the build time a bit but ensures that the depot content is consistent with
your source tree at all times.
! RUN_OPT += --depot-auto-update
Building the 'sculpt-installation' package works analogously to the 'sculpt'
package.

View File

@ -3,6 +3,7 @@ _/pkg/wifi
_/pkg/depot_download
_/pkg/terminal
_/src/report_rom
_/src/clipboard
_/src/init
_/src/ram_fs
_/src/fs_rom

View File

@ -3,11 +3,13 @@
<requires>
<nitpicker label="focus"/>
<nitpicker/>
<report/>
<report label="shape"/>
<report label="clipboard"/>
<rom label="clipboard"/>
<timer/>
</requires>
<provides> <nitpicker/> <report/> </provides>
<provides> <nitpicker/> <report/> <rom/> </provides>
<content>
<rom label="ld.lib.so"/>

View File

@ -0,0 +1 @@
File system for providing access to Genode tracing

View File

@ -0,0 +1,3 @@
_/src/trace_policy
_/src/vfs
_/src/vfs_trace

View File

@ -0,0 +1 @@
2019-07-08 e96823d8956e3a27b07dfe8936a58e7dfda0e228

View File

@ -0,0 +1,19 @@
<runtime ram="48M" caps="150" binary="vfs">
<provides> <file_system/> </provides>
<requires> <trace/> </requires>
<content>
<rom label="vfs"/>
<rom label="ld.lib.so"/>
<rom label="vfs_trace.lib.so"/>
<rom label="vfs.lib.so"/>
<rom label="null"/>
</content>
<config>
<vfs> <trace ram="32M"/> </vfs>
<default-policy root="/" writeable="yes"/>
</config>
</runtime>

View File

@ -3,7 +3,9 @@
<requires>
<nitpicker label="focus"/>
<nitpicker/>
<report/>
<report label="shape"/>
<report label="clipboard"/>
<rom label="clipboard"/>
<timer/>
</requires>

View File

@ -19,7 +19,11 @@
<default-policy> <child name="wm"/> </default-policy>
</service>
<service name="Report"> <!-- for reporting 'shape' reports through the wm -->
<service name="Report"> <!-- for reporting 'shape' and 'clipboard' reports through the wm -->
<default-policy> <child name="wm"/> </default-policy>
</service>
<service name="ROM"> <!-- for accessing 'clipboard' ROMs through the wm -->
<default-policy> <child name="wm"/> </default-policy>
</service>
@ -45,7 +49,7 @@
<start name="wm" caps="250">
<resource name="RAM" quantum="6M"/>
<provides>
<service name="Nitpicker"/> <service name="Report"/>
<service name="Nitpicker"/> <service name="Report"/> <service name="ROM"/>
</provides>
<config>
<policy label_prefix="decorator" role="decorator"/>
@ -56,6 +60,8 @@
<service name="ROM" label="resize_request"> <child name="report_rom"/> </service>
<service name="ROM" label="focus"> <child name="report_rom"/> </service>
<service name="Report" label_last="shape"> <parent/> </service>
<service name="Report" label_last="clipboard"> <parent/> </service>
<service name="ROM" label_last="clipboard"> <parent/> </service>
<service name="Report"> <child name="report_rom"/> </service>
<service name="Nitpicker" label=""> <parent label="focus"/> </service>
<any-service>
@ -75,9 +81,9 @@
<service name="ROM" label="decorator_margins"> <child name="report_rom"/> </service>
<service name="ROM" label="rules"> <child name="report_rom"/> </service>
<service name="Report"> <child name="report_rom"/> </service>
<any-service>
<child name="wm"/> <parent/> <any-child/>
</any-service>
<service name="Nitpicker"> <child name="wm"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
@ -92,10 +98,9 @@
<service name="ROM" label="pointer"> <child name="report_rom"/> </service>
<service name="Report" label="decorator_margins"> <child name="report_rom"/> </service>
<service name="Report" label="hover"> <child name="report_rom"/> </service>
<service name="Nitpicker"> <child name="wm"/> </service>
<any-service>
<child name="wm"/> <parent/> <any-child/>
</any-service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
</config>

View File

@ -20,36 +20,39 @@
</service>
<service name="ROM">
<policy label_suffix="layouter -> window_list">
<policy label_suffix=" -> window_list">
<child name="report_rom" label="layouter -> window_list"/> </policy>
<policy label_suffix="layouter -> focus_request">
<policy label_suffix=" -> focus_request">
<child name="report_rom" label="layouter -> focus_request"/> </policy>
<policy label_suffix="layouter -> hover">
<policy label_suffix=" -> hover">
<child name="report_rom" label="layouter -> hover"/> </policy>
<policy label_suffix="layouter -> decorator_margins">
<policy label_suffix=" -> decorator_margins">
<child name="report_rom" label="layouter -> decorator_margins"/> </policy>
<policy label_suffix="layouter -> rules">
<policy label_suffix=" -> rules">
<child name="report_rom" label="layouter -> rules"/> </policy>
<policy label_suffix="decorator -> window_layout">
<policy label_suffix=" -> window_layout">
<child name="report_rom" label="decorator -> window_layout"/> </policy>
<policy label_suffix="decorator -> pointer">
<policy label_suffix=" -> pointer">
<child name="report_rom" label="decorator -> pointer"/> </policy>
<policy label_suffix=" -> clipboard">
<child name="wm"/> </policy>
</service>
<service name="Report">
<policy label_suffix="layouter -> window_layout">
<policy label_suffix=" -> window_layout">
<child name="report_rom" label="layouter -> window_layout"/> </policy>
<policy label_suffix="layouter -> resize_request">
<policy label_suffix=" -> resize_request">
<child name="report_rom" label="layouter -> resize_request"/> </policy>
<policy label_suffix="layouter -> focus">
<policy label_suffix=" -> focus">
<child name="report_rom" label="layouter -> focus"/> </policy>
<policy label_suffix="layouter -> rules">
<policy label_suffix=" -> rules">
<child name="report_rom" label="layouter -> rules"/> </policy>
<policy label_suffix="decorator -> hover">
<policy label_suffix=" -> hover">
<child name="report_rom" label="decorator -> hover"/> </policy>
<policy label_suffix="decorator -> decorator_margins">
<policy label_suffix=" -> decorator_margins">
<child name="report_rom" label="decorator -> decorator_margins"/> </policy>
<policy label_suffix="-> shape"> <child name="wm"/> </policy>
<policy label_suffix=" -> shape"> <child name="wm"/> </policy>
<policy label_suffix=" -> clipboard"> <child name="wm"/> </policy>
</service>
<start name="report_rom">
@ -74,7 +77,7 @@
<start name="wm" caps="250">
<resource name="RAM" quantum="8M"/>
<provides>
<service name="Nitpicker"/> <service name="Report"/>
<service name="Nitpicker"/> <service name="Report"/> <service name="ROM"/>
</provides>
<config>
<policy label_suffix="decorator -> " role="decorator"/>
@ -84,8 +87,10 @@
<route>
<service name="ROM" label="resize_request"> <child name="report_rom"/> </service>
<service name="ROM" label="focus"> <child name="report_rom"/> </service>
<service name="Report" label_last="shape"> <parent/> </service>
<service name="Report"> <child name="report_rom"/> </service>
<service name="ROM" label_last="clipboard"> <parent/> </service>
<service name="Report" label_last="clipboard"> <parent/> </service>
<service name="Report" label_last="shape"> <parent/> </service>
<service name="Report"> <child name="report_rom"/> </service>
<service name="Nitpicker" label=""> <parent label="focus"/> </service>
<any-service> <parent/> </any-service>
</route>

View File

@ -153,6 +153,13 @@ install_config {
<service name="Timer"> <parent/> </service>
</common_routes>
<start name="recall_fs" pkg="} [depot_user]/pkg/[current_pkg chroot] {">
<route>
<service name="File_system"> <parent/> </service>
</route>
<config> <default-policy path_prefix="/recall" writeable="yes"/> </config>
</start>
<start name="wm" pkg="} [depot_user]/pkg/[current_pkg wm] {">
<route>
<service name="Nitpicker"> <parent/> </service>
@ -168,6 +175,7 @@ install_config {
<service name="ROM" label="rules"> <child name="wm"/> </service>
<service name="Report"> <child name="wm"/> </service>
<service name="Nitpicker"> <child name="wm"/> </service>
<service name="File_system" label="recall"> <child name="recall_fs"/> </service>
</route>
</start>
@ -180,7 +188,6 @@ install_config {
</route>
</start>
<start name="backdrop" pkg="} [depot_user]/pkg/[current_pkg sticks_blue_backdrop] {">
<route>
<service name="Nitpicker"> <parent label="backdrop"/> </service>

View File

@ -1,6 +1,6 @@
create_boot_directory
if {[have_spec linux] || [have_spec imx7d_sabre] ||
if {[have_spec linux] || [have_spec rpi3] ||
[expr [have_spec imx53] && [have_spec trustzone]]} {
puts "Run script does not support this platform."
exit 0

View File

@ -143,7 +143,7 @@ install_config {
<start name="wm" caps="200">
<resource name="RAM" quantum="6M"/>
<provides>
<service name="Nitpicker"/> <service name="Report"/>
<service name="Nitpicker"/> <service name="Report"/> <service name="ROM"/>
</provides>
<config>
<policy label_prefix="decorator" role="decorator"/>

View File

@ -61,6 +61,7 @@ install_config {
<policy label="pointer -> xray"
report="global_keys_handler -> leitzentrale"/>
<policy label="pointer -> shape" report="shape"/>
<policy label="clipboard -> focus" report="nitpicker -> focus"/>
<policy label="drivers -> capslock" report="global_keys_handler -> capslock"/>
<policy label="runtime -> capslock" report="global_keys_handler -> capslock"/>
<policy label="drivers -> numlock" report="global_keys_handler -> numlock"/>
@ -112,6 +113,7 @@ install_config {
<rom name="drivers" label="drivers.config"/>
<rom name="deploy" label="manual_deploy.config"/>
<rom name="usb" label="usb.config"/>
<rom name="clipboard" label="clipboard.config"/>
<rom name="en_us.chargen"/>
<rom name="fr.chargen"/>
<rom name="de.chargen"/>
@ -369,6 +371,19 @@ install_config {
</route>
</start>
<start name="clipboard" priority="-2">
<resource name="RAM" quantum="2M"/>
<provides>
<service name="ROM"/> <service name="Report"/>
</provides>
<route>
<service name="ROM" label="config">
<child name="config_fs_rom" label="clipboard"/> </service>
<service name="ROM" label="focus"> <child name="report_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="leitzentrale" caps="4000" priority="-2">
<binary name="init"/>
<resource name="RAM" quantum="164M"/>
@ -442,6 +457,12 @@ install_config {
<service name="Nitpicker"> <child name="nitpicker"/> </service>
<service name="Timer"> <child name="timer"/> </service>
<service name="Report" label_suffix="-> shape"> <child name="pointer"/> </service>
<service name="Report" label="inspect terminal -> clipboard">
<child name="clipboard" label="leitzentrale -> manager -> fader -> -> clipboard"/> </service>
<service name="ROM" label="inspect terminal -> clipboard">
<child name="clipboard" label="leitzentrale -> manager -> fader -> -> clipboard"/> </service>
<service name="Report" label_suffix="-> clipboard"> <child name="clipboard"/> </service>
<service name="ROM" label_suffix="-> clipboard"> <child name="clipboard"/> </service>
<service name="Report" label="runtime_view -> hover">
<child name="report_rom"/> </service>
<service name="Report"> <child name="fs_report"/> </service>
@ -498,7 +519,7 @@ exec gzip -dc [genode_dir]/repos/gems/run/sculpt/machine.vdi.gz > [run_dir]/geno
# Note: the string must be exactly 5 bytes long.
#
proc sculpt_version { } {
return "19.06" }
return "19.07" }
# write file with newline (for producing nice output when using 'cat /VERSION')
set fd [open [run_dir]/genode/VERSION w]

View File

@ -0,0 +1,6 @@
<config verbose="no" match_labels="yes">
<flow from="leitzentrale" to="desktop" />
<flow from="desktop" to="leitzentrale" />
<policy label_prefix="leitzentrale" domain="leitzentrale"/>
<default-policy domain="desktop"/>
</config>

View File

@ -1,4 +1,4 @@
<config>
<config copy="yes" paste="yes">
<vfs>
<rom name="Vera.ttf"/>
<rom name="VeraMono.ttf"/>

View File

@ -107,7 +107,9 @@
<start name="wm" caps="200">
<resource name="RAM" quantum="2M"/>
<provides> <service name="Nitpicker"/> <service name="Report"/> </provides>
<provides>
<service name="Nitpicker"/> <service name="Report"/> <service name="ROM"/>
</provides>
<config>
<policy label_prefix="decorator" role="decorator"/>
<default-policy/>

View File

@ -45,6 +45,7 @@
<SharedFolders>
<SharedFolder name="shared" hostPath="/shared" writable="true" autoMount="true"/>
</SharedFolders>
<Clipboard mode="Bidirectional"/>
</Hardware>
<StorageControllers>
<StorageController name="SATA" type="AHCI" PortCount="4" useHostIOCache="true" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3">

View File

@ -74,7 +74,9 @@ install_config {
<start name="wm" caps="1000">
<resource name="RAM" quantum="32M"/>
<binary name="init"/>
<provides> <service name="Nitpicker"/> <service name="Report"/> </provides>
<provides>
<service name="Nitpicker"/> <service name="Report"/> <service name="ROM"/>
</provides>
<route>
<service name="ROM" label="config"> <parent label="wm.config"/> </service>
<service name="Nitpicker"> <child name="nitpicker"/> </service>
@ -151,8 +153,8 @@ close $fd
file copy -force [genode_dir]/repos/gems/recipes/raw/motif_wm/wm.config [run_dir]/genode/
build { app/decorator server/nitpicker server/wm test/nitpicker }
build { app/window_layouter app/decorator server/nitpicker server/wm test/nitpicker }
build_boot_image { decorator nitpicker wm testnit }
build_boot_image { window_layouter decorator nitpicker wm testnit }
run_genode_until forever

View File

@ -232,7 +232,7 @@ class Depot_deploy::Child : public List_model<Child>::Element
: Xml_node("<empty/>");
if (_condition == UNSATISFIED && _start_xml.constructed())
fn(_start_xml->xml(), launcher_xml);
fn(_start_xml->xml(), launcher_xml, _name);
}
void mark_as_incomplete(Xml_node missing)

View File

@ -18,11 +18,19 @@
#include <os/reporter.h>
#include <gems/vfs.h>
#include <depot/archive.h>
#include <gems/lru_cache.h>
namespace Depot_query {
using namespace Depot;
typedef String<64> Rom_label;
struct Recursion_limit;
struct Dependencies;
class Stat_cache;
struct Rom_query;
class Cached_rom_query;
struct Main;
}
@ -144,7 +152,172 @@ class Depot_query::Dependencies
};
struct Depot_query::Main
class Depot_query::Stat_cache
{
private:
struct Key
{
struct Value
{
Archive::Path path;
bool operator > (Value const &other) const
{
return strcmp(path.string(), other.path.string()) > 0;
}
bool operator == (Value const &other) const
{
return path == other.path;
}
} value;
};
struct Result { bool file_exists; };
typedef Lru_cache<Key, Result> Cache;
Cache::Size const _size;
Cache _cache;
Directory const &_dir;
public:
Stat_cache(Directory const &dir, Allocator &alloc, Xml_node const config)
:
_size({.value = config.attribute_value("stat_cache", Number_of_bytes(64*1024))
/ Cache::element_size()}),
_cache(alloc, _size),
_dir(dir)
{ }
bool file_exists(Archive::Path const path)
{
/* don't cache the state of the 'local' depot user */
if (Archive::user(path) == "local")
return _dir.file_exists(path);
bool result = false;
auto hit_fn = [&] (Result const &cached_result)
{
result = cached_result.file_exists;
};
auto miss_fn = [&] (Cache::Missing_element &missing_element)
{
Result const stat_result { _dir.file_exists(path) };
/*
* Don't cache negative results because files may appear
* during installation. Later queries may find files absent
* from earlier queries.
*/
if (stat_result.file_exists)
missing_element.construct(stat_result);
};
Key const key { .value = { .path = path } };
(void)_cache.try_apply(key, hit_fn, miss_fn);
return result;
}
};
struct Depot_query::Rom_query : Interface
{
/**
* Look up ROM module 'rom_label' in the archives referenced by 'pkg_path'
*
* \throw Directory::Nonexistent_directory
* \throw Directory::Nonexistent_file
* \throw File::Truncated_during_read
* \throw Recursion_limit::Reached
*/
virtual Archive::Path find_rom_in_pkg(Directory::Path const &pkg_path,
Rom_label const &rom_label,
Recursion_limit recursion_limit) = 0;
};
class Depot_query::Cached_rom_query : public Rom_query
{
private:
struct Key
{
struct Value
{
Archive::Path pkg;
Rom_label rom;
bool operator > (Value const &other) const
{
return strcmp(pkg.string(), other.pkg.string()) > 0
&& strcmp(rom.string(), other.rom.string()) > 0;
}
bool operator == (Value const &other) const
{
return pkg == other.pkg && rom == other.rom;
}
} value;
};
typedef Lru_cache<Key, Archive::Path> Cache;
Cache::Size const _size;
Cache mutable _cache;
Rom_query &_rom_query;
public:
Cached_rom_query(Rom_query &rom_query, Allocator &alloc, Xml_node const config)
:
_size({.value = config.attribute_value("rom_query_cache", Number_of_bytes(64*1024))
/ Cache::element_size() }),
_cache(alloc, _size),
_rom_query(rom_query)
{ }
Archive::Path find_rom_in_pkg(Directory::Path const &pkg_path,
Rom_label const &rom_label,
Recursion_limit recursion_limit) override
{
/* don't cache the state of the 'local' depot user */
if (Archive::user(pkg_path) == "local")
return _rom_query.find_rom_in_pkg(pkg_path, rom_label, recursion_limit);
Archive::Path result { };
auto hit_fn = [&] (Archive::Path const &path) { result = path; };
auto miss_fn = [&] (Cache::Missing_element &missing_element)
{
Archive::Path const path =
_rom_query.find_rom_in_pkg(pkg_path, rom_label, recursion_limit);
if (path.valid())
missing_element.construct(path);
};
Key const key { .value = { .pkg = pkg_path, .rom = rom_label } };
(void)_cache.try_apply(key, hit_fn, miss_fn);
return result;
}
};
struct Depot_query::Main : private Rom_query
{
Env &_env;
@ -158,6 +331,8 @@ struct Depot_query::Main
Directory _depot_dir { _root, "depot" };
Stat_cache _depot_stat_cache { _depot_dir, _heap, _config.xml() };
Signal_handler<Main> _config_handler {
_env.ep(), *this, &Main::_handle_config };
@ -182,7 +357,6 @@ struct Depot_query::Main
obj.destruct();
}
typedef String<64> Rom_label;
typedef String<16> Architecture;
typedef String<32> Version;
@ -210,17 +384,13 @@ struct Depot_query::Main
});
}
Cached_rom_query _cached_rom_query { *this, _heap, _config.xml() };
/**
* Look up ROM module 'rom_label' in the archives referenced by 'pkg_path'
*
* \throw Directory::Nonexistent_directory
* \throw Directory::Nonexistent_file
* \throw File::Truncated_during_read
* \throw Recursion_limit::Reached
* Rom_query interface
*/
Archive::Path _find_rom_in_pkg(Directory::Path const &pkg_path,
Rom_label const &rom_label,
Recursion_limit recursion_limit);
Archive::Path find_rom_in_pkg(Directory::Path const &, Rom_label const &,
Recursion_limit) override;
void _query_blueprint(Directory::Path const &, Xml_generator &);
void _collect_source_dependencies(Archive::Path const &, Dependencies &, Recursion_limit);
@ -344,9 +514,9 @@ struct Depot_query::Main
Depot_query::Archive::Path
Depot_query::Main::_find_rom_in_pkg(Directory::Path const &pkg_path,
Rom_label const &rom_label,
Recursion_limit recursion_limit)
Depot_query::Main::find_rom_in_pkg(Directory::Path const &pkg_path,
Rom_label const &rom_label,
Recursion_limit recursion_limit)
{
/*
* \throw Directory::Nonexistent_directory
@ -375,7 +545,7 @@ Depot_query::Main::_find_rom_in_pkg(Directory::Path const &pkg_path,
Archive::name(archive_path), "/",
Archive::version(archive_path), "/", rom_label);
if (_depot_dir.file_exists(rom_path))
if (_depot_stat_cache.file_exists(rom_path))
result = rom_path;
}
break;
@ -387,16 +557,19 @@ Depot_query::Main::_find_rom_in_pkg(Directory::Path const &pkg_path,
Archive::name(archive_path), "/",
Archive::version(archive_path), "/", rom_label);
if (_depot_dir.file_exists(rom_path))
if (_depot_stat_cache.file_exists(rom_path))
result = rom_path;
}
break;
case Archive::PKG:
Archive::Path const result_from_pkg =
_find_rom_in_pkg(archive_path, rom_label, recursion_limit);
_cached_rom_query.find_rom_in_pkg(archive_path, rom_label, recursion_limit);
if (result_from_pkg.valid())
result = result_from_pkg;
break;
}
});
@ -448,7 +621,7 @@ void Depot_query::Main::_query_blueprint(Directory::Path const &pkg_path, Xml_ge
}
Archive::Path const rom_path =
_find_rom_in_pkg(pkg_path, label, Recursion_limit{8});
_cached_rom_query.find_rom_in_pkg(pkg_path, label, Recursion_limit{8});
if (rom_path.valid()) {
xml.node("rom", [&] () {

View File

@ -61,8 +61,6 @@ struct Gpt::Writer
Util::Number_of_bytes _entry_alignment { 4096u };
Genode::Xml_node *_config { nullptr };
void _handle_config(Genode::Xml_node config)
{
_verbose = config.attribute_value("verbose", false);
@ -83,8 +81,6 @@ struct Gpt::Writer
if (_wipe && (_initialize || commands)) {
Genode::warning("will exit after wiping");
}
_config = &config;
}
/************
@ -692,15 +688,13 @@ struct Gpt::Writer
* \return true if actions were executed successfully, otherwise
* false
*/
bool execute_actions()
bool execute_actions(Genode::Xml_node actions)
{
if (_wipe) { return _wipe_tables(); }
if (_initialize) { _initialize_tables(); }
try {
Genode::Xml_node actions = _config->sub_node("actions");
actions.for_each_sub_node([&] (Genode::Xml_node node) {
bool result = false;
@ -750,14 +744,19 @@ struct Main
Util::init_random(_heap);
Genode::Xml_node const config = _config_rom.xml();
try {
_writer.construct(_block, _config_rom.xml());
_writer.construct(_block, config);
} catch (...) {
_env.parent().exit(1);
return;
}
bool const success = _writer->execute_actions();
bool success = false;
config.with_sub_node("actions", [&] (Genode::Xml_node actions) {
success = _writer->execute_actions(actions); });
_env.parent().exit(success ? 0 : 1);
}
};

View File

@ -92,8 +92,8 @@ namespace Util {
/* handle suffixes */
if (i > 0)
switch (s[i]) {
case 'G': res *= 1024;
case 'M': res *= 1024;
case 'G': res *= 1024; [[fallthrough]];
case 'M': res *= 1024; [[fallthrough]];
case 'K': res *= 1024; i++;
default: break;
}

View File

@ -42,10 +42,8 @@ void Sculpt::Deploy::gen_child_diagnostics(Xml_generator &xml) const
typedef Registered_no_delete<Message> Registered_message;
Registry<Registered_message> messages { };
auto gen_missing_dependencies = [&] (Xml_node start)
auto gen_missing_dependencies = [&] (Xml_node start, Start_name const &name)
{
Start_name const name = start.attribute_value("name", Start_name());
_for_each_missing_server(start, [&] (Start_name const &server) {
Message const new_message(Pretty(name), " requires ", Pretty(server));
@ -60,9 +58,10 @@ void Sculpt::Deploy::gen_child_diagnostics(Xml_generator &xml) const
});
};
_children.for_each_unsatisfied_child([&] (Xml_node start, Xml_node launcher) {
gen_missing_dependencies(start);
gen_missing_dependencies(launcher);
_children.for_each_unsatisfied_child([&] (Xml_node start, Xml_node launcher,
Start_name const &name) {
gen_missing_dependencies(start, name);
gen_missing_dependencies(launcher, name);
});
/*

View File

@ -174,7 +174,7 @@ struct Sculpt::Deploy
bool any_unsatisfied_child() const
{
bool all_satisfied = true;
_children.for_each_unsatisfied_child([&] (Xml_node, Xml_node) {
_children.for_each_unsatisfied_child([&] (Xml_node, Xml_node, Start_name const &) {
all_satisfied = false; });
return !all_satisfied;
}

View File

@ -18,6 +18,7 @@
#include <os/reporter.h>
#include <nitpicker_session/connection.h>
#include <vm_session/vm_session.h>
#include <timer_session/connection.h>
/* included from depot_deploy tool */
#include <children.h>
@ -213,14 +214,15 @@ struct Sculpt::Main : Input_event_handler,
return _query_version;
}
/**
* Depot_query interface
*/
void trigger_depot_query() override
{
_query_version.value++;
Timer::Connection _timer { _env };
Timer::One_shot_timeout<Main> _deferred_depot_query_handler {
_timer, *this, &Main::_handle_deferred_depot_query };
void _handle_deferred_depot_query(Duration)
{
if (_deploy._arch.valid()) {
_query_version.value++;
_depot_query_reporter.generate([&] (Xml_generator &xml) {
xml.attribute("arch", _deploy._arch);
xml.attribute("version", _query_version.value);
@ -233,6 +235,21 @@ struct Sculpt::Main : Input_event_handler,
}
}
/**
* Depot_query interface
*/
void trigger_depot_query() override
{
/*
* Defer the submission of the query for a few milliseconds because
* 'trigger_depot_query' may be consecutively called several times
* while evaluating different conditions. Without deferring, the depot
* query component would produce intermediate results that take time
* but are ultimately discarded.
*/
_deferred_depot_query_handler.schedule(Microseconds{5000});
}
/*********************
** Blueprint query **
@ -249,6 +266,16 @@ struct Sculpt::Main : Input_event_handler,
Xml_node const blueprint = _blueprint_rom.xml();
/*
* Drop intermediate results that will be superseded by a newer query.
* This is important because an outdated blueprint would be disregarded
* by 'handle_deploy' anyway while at the same time a new query is
* issued. This can result a feedback loop where blueprints are
* requested but never applied.
*/
if (blueprint.attribute_value("version", 0U) != _query_version.value)
return;
_runtime_state.apply_to_construction([&] (Component &component) {
_popup_dialog.apply_blueprint(component, blueprint); });
@ -930,6 +957,8 @@ void Sculpt::Main::_handle_nitpicker_mode()
_gui.font_size(text_size);
_fonts_config.generate([&] (Xml_generator &xml) {
xml.attribute("copy", true);
xml.attribute("paste", true);
xml.node("vfs", [&] () {
gen_named_node(xml, "rom", "Vera.ttf");
gen_named_node(xml, "rom", "VeraMono.ttf");

View File

@ -122,8 +122,13 @@ struct Sculpt::Route : List_model<Route>::Element
gen_named_node(xml, "service", Service::name_attr(required), [&] () {
if (required_label.valid())
xml.attribute("label", required_label);
if (required_label.valid()) {
if (selected_service->match_label == Service::Match_label::LAST)
xml.attribute("label_last", required_label);
else
xml.attribute("label", required_label);
}
selected_service->gen_xml(xml);
});

View File

@ -324,6 +324,9 @@ class Sculpt::Runtime_config
_pf_info { _r, Type::ROM, "platform information", "platform_info" },
_system { _r, Type::ROM, "system status", "config -> system" },
_report { _r, Type::REPORT, "system reports" },
_shape { _r, Type::REPORT, "pointer shape", "shape", Service::Match_label::LAST },
_copy { _r, Type::REPORT, "global clipboard", "clipboard", Service::Match_label::LAST },
_paste { _r, Type::ROM, "global clipboard", "clipboard", Service::Match_label::LAST },
_rm { _r, Type::RM, "custom virtual memory objects" },
_io_mem { _r, Type::IO_MEM, "raw hardware access" },
_io_port { _r, Type::IO_PORT, "raw hardware access" },

View File

@ -29,10 +29,13 @@ struct Sculpt::Service
RM, IO_MEM, IO_PORT, IRQ, REPORT, ROM, TERMINAL, TRACE,
USB, RTC, PLATFORM, VM, UNDEFINED };
Start_name server { }; /* invalid for parent service */
Type type;
Label label;
Info info;
enum class Match_label { EXACT, LAST };
Start_name server { }; /* invalid for parent service */
Type type;
Label label;
Info info;
Match_label match_label { Match_label::EXACT };
/**
* Return name attribute value of <service name="..."> node
@ -72,8 +75,11 @@ struct Sculpt::Service
/**
* Constructor for parent service
*/
Service(Type type, Info const &info, Label const &label = Label())
: type(type), label(label), info(info) { }
Service(Type type, Info const &info, Label const &label = Label(),
Match_label match_label = Match_label::EXACT)
:
type(type), label(label), info(info), match_label(match_label)
{ }
void gen_xml(Xml_generator &xml) const
{
@ -84,7 +90,7 @@ struct Sculpt::Service
if (!parent)
xml.attribute("name", server);
if (label.valid())
if (label.valid() && match_label == Match_label::EXACT)
xml.attribute("label", label);
});
}

View File

@ -91,6 +91,11 @@ void Sculpt::gen_terminal_start(Xml_generator &xml, Rom_name const &name,
gen_parent_route<Pd_session> (xml);
gen_parent_route<Log_session> (xml);
gen_parent_route<Timer::Session> (xml);
gen_parent_route<Report::Session>(xml);
gen_named_node(xml, "service", Rom_session::service_name(), [&] () {
xml.attribute("label", "clipboard");
xml.node("parent", [&] () { }); });
gen_named_node(xml, "service", Rom_session::service_name(), [&] () {
xml.attribute("label", "config");

View File

@ -261,33 +261,18 @@ void Decorator::Main::_handle_nitpicker_sync()
auto flush_window_stack_changes = [&] () {
_window_stack.update_nitpicker_views(); };
if (_window_layout_update_needed && _window_layout.valid()) {
if (_window_layout_update_needed) {
try {
Xml_node xml(_window_layout.local_addr<char>(),
_window_layout.size());
_window_stack.update_model(_window_layout.xml(), flush_window_stack_changes);
_window_stack.update_model(xml, flush_window_stack_changes);
model_updated = true;
model_updated = true;
/*
* A decorator element might have appeared or disappeared under
* the pointer.
*/
if (_pointer.constructed() && _pointer->valid())
update_hover_report(Xml_node(_pointer->local_addr<char>()),
_window_stack, _hover, _hover_reporter);
} catch (Xml_node::Invalid_syntax) {
/*
* An error occured with processing the XML model. Flush the
* internal representation.
*/
_window_stack.update_model(Xml_node("<window_layout/>"),
flush_window_stack_changes);
}
/*
* A decorator element might have appeared or disappeared under
* the pointer.
*/
if (_pointer.constructed())
update_hover_report(_pointer->xml(), _window_stack, _hover, _hover_reporter);
_window_layout_update_needed = false;
}
@ -317,9 +302,7 @@ void Decorator::Main::_handle_pointer_update()
_pointer->update();
if (_pointer->valid())
update_hover_report(Xml_node(_pointer->local_addr<char>()),
_window_stack, _hover, _hover_reporter);
update_hover_report(_pointer->xml(), _window_stack, _hover, _hover_reporter);
}

View File

@ -23,6 +23,10 @@ Decorator::Window_base::Hover Decorator::Window::hover(Point abs_pos) const
hover.window_id = id();
/* omit the decoration checks below whenever the content is hovered */
if (geometry().contains(abs_pos))
return hover;
Rect const closer_geometry =
_theme.absolute(_theme.element_geometry(Theme::ELEMENT_TYPE_CLOSER),
outer_geometry());

View File

@ -115,6 +115,8 @@ class Window_layouter::Assign : public List_model<Assign>::Element
return Rect(outer.p1() + target_geometry.p1(), outer.area());
}
bool maximized() const { return _maximized; }
/**
* Call 'fn' with 'Registry<Member>' if label matches assignment
*

View File

@ -48,7 +48,9 @@ struct Window_layouter::Main : Operations,
Timer::Connection _drop_timer { _env };
bool _defer_layout_change = false;
enum class Drag_state { IDLE, DRAGGING, SETTLING };
Drag_state _drag_state { Drag_state::IDLE };
Signal_handler<Main> _drop_timer_handler {
_env.ep(), *this, &Main::_handle_drop_timer };
@ -116,6 +118,7 @@ struct Window_layouter::Main : Operations,
target.geometry(),
_decorator_margins);
member.window.outer_geometry(rect);
member.window.maximized(assign.maximized());
});
});
});
@ -137,21 +140,9 @@ struct Window_layouter::Main : Operations,
*/
void layout_rules_changed() override
{
/*
* When re-importing rules generated by the drop operation, issue an
* updated resize request immediately instead of waiting for the
* '_drop_timer_handler'. Clear '_defer_layout_change' before calling
* '_update_window_layout' because '_gen_window_layout' evaluates
* this flag.
*/
bool const issue_resize_request = _defer_layout_change;
_defer_layout_change = false;
_update_window_layout();
if (issue_resize_request)
_gen_resize_request();
_gen_resize_request();
}
/**
@ -219,6 +210,11 @@ struct Window_layouter::Main : Operations,
void drag(Window_id id, Window::Element element, Point clicked, Point curr) override
{
if (_drag_state == Drag_state::SETTLING)
return;
_drag_state = Drag_state::DRAGGING;
to_front(id);
bool window_layout_changed = false;
@ -244,11 +240,15 @@ struct Window_layouter::Main : Operations,
void _handle_drop_timer()
{
/* discharge '_defer_layout_change' */
layout_rules_changed();
_drag_state = Drag_state::IDLE;
_gen_rules();
_window_list.for_each_window([&] (Window &window) {
window.finalize_drag_operation(); });
}
void finalize_drag(Window_id id, Window::Element, Point, Point) override
void finalize_drag(Window_id, Window::Element, Point, Point) override
{
/*
* Update window layout because highlighting may have changed after the
@ -256,17 +256,9 @@ struct Window_layouter::Main : Operations,
* dragging of a resize handle, the resize handle is no longer hovered.
*/
_gen_window_layout();
_gen_rules();
_window_list.with_window(id, [&] (Window &window) {
window.finalize_drag_operation(); });
_drag_state = Drag_state::SETTLING;
/*
* Mask the generation of resize requests until the updated rules are
* imported the next time. Discharge the masking after a timeout for
* the case where rules fixed and not fed back to the layouter.
*/
_defer_layout_change = true;
_drop_timer.trigger_once(250*1000);
}
@ -399,9 +391,6 @@ struct Window_layouter::Main : Operations,
void Window_layouter::Main::_gen_window_layout()
{
if (_defer_layout_change)
return;
/* update hover and focus state of each window */
_window_list.for_each_window([&] (Window &window) {
@ -419,9 +408,6 @@ void Window_layouter::Main::_gen_window_layout()
void Window_layouter::Main::_gen_resize_request()
{
if (_defer_layout_change)
return;
bool resize_needed = false;
_assign_list.for_each([&] (Assign const &assign) {
assign.for_each_member([&] (Assign::Member const &member) {

View File

@ -187,21 +187,24 @@ class Window_layouter::Window : public List_model<Window>::Element
{
_dragged_element = element;
_drag_left_border = (element.type == Window::Element::LEFT)
|| (element.type == Window::Element::TOP_LEFT)
|| (element.type == Window::Element::BOTTOM_LEFT);
if (_resizeable) {
_drag_right_border = (element.type == Window::Element::RIGHT)
|| (element.type == Window::Element::TOP_RIGHT)
|| (element.type == Window::Element::BOTTOM_RIGHT);
_drag_left_border = (element.type == Window::Element::LEFT)
|| (element.type == Window::Element::TOP_LEFT)
|| (element.type == Window::Element::BOTTOM_LEFT);
_drag_top_border = (element.type == Window::Element::TOP)
|| (element.type == Window::Element::TOP_LEFT)
|| (element.type == Window::Element::TOP_RIGHT);
_drag_right_border = (element.type == Window::Element::RIGHT)
|| (element.type == Window::Element::TOP_RIGHT)
|| (element.type == Window::Element::BOTTOM_RIGHT);
_drag_bottom_border = (element.type == Window::Element::BOTTOM)
|| (element.type == Window::Element::BOTTOM_LEFT)
|| (element.type == Window::Element::BOTTOM_RIGHT);
_drag_top_border = (element.type == Window::Element::TOP)
|| (element.type == Window::Element::TOP_LEFT)
|| (element.type == Window::Element::TOP_RIGHT);
_drag_bottom_border = (element.type == Window::Element::BOTTOM)
|| (element.type == Window::Element::BOTTOM_LEFT)
|| (element.type == Window::Element::BOTTOM_RIGHT);
}
_orig_geometry = _geometry;
_drag_geometry = _geometry;
@ -463,12 +466,13 @@ class Window_layouter::Window : public List_model<Window>::Element
void finalize_drag_operation()
{
_dragged = false;
_drag_left_border = false;
_drag_right_border = false;
_drag_top_border = false;
_drag_bottom_border = false;
_dragged_size = effective_inner_geometry().area();
_geometry = effective_inner_geometry();
_dragged_size = _geometry.area();
_dragged = false;
}
void to_front_cnt(unsigned to_front_cnt) { _to_front_cnt = to_front_cnt; }

View File

@ -1,14 +1,14 @@
This is a graphical terminal implementation. It provides the Terminal
service and uses a nitpicker session for screen representation.
Configuration
~~~~~~~~~~~~~
Color configuration
~~~~~~~~~~~~~~~~~~~
The default color palette can be configured via the <palette> XML
configuration node like follows. There are 16 colors configurable -
index 0-7 normal color and index 8-15 bright (bold) colors.
! <config>
! <palette>
! <color index="0" value="#000000"/> <!-- black is real black -->
@ -17,3 +17,17 @@ index 0-7 normal color and index 8-15 bright (bold) colors.
! ...
! </config>
Clipboard support
~~~~~~~~~~~~~~~~~
With the '<config>' attribute 'copy="yes"' specified, the terminal allows
the user to select text to be reported to a "clipboard" report. The selection
mode is activated by holding the left shift key. While the selection mode
is active, the text position under mouse pointer is highlighted and the
user can select text via the left mouse button. Upon release of the mouse
button, the selection is reported.
Vice versa, with the '<config>' attribute 'paste="yes"' specified, the
terminal allows the user to paste the content of a "clipboard" ROM session
to the terminal client by pressing the middle mouse button.

View File

@ -47,7 +47,7 @@ class Terminal::Color_palette
" <color index=\"1\" value=\"#AC4142\"/>" /* red */
" <color index=\"2\" value=\"#90A959\"/>" /* green */
" <color index=\"3\" value=\"#F4BF75\"/>" /* yellow */
" <color index=\"4\" value=\"#6A9FB5\"/>" /* blue */
" <color index=\"4\" value=\"#7686BD\"/>" /* blue */
" <color index=\"5\" value=\"#AA759F\"/>" /* magenta */
" <color index=\"6\" value=\"#75B5AA\"/>" /* cyan */
" <color index=\"7\" value=\"#D0D0D0\"/>" /* white */

View File

@ -21,6 +21,7 @@
#include <base/attached_rom_dataspace.h>
#include <base/attached_ram_dataspace.h>
#include <input/event.h>
#include <os/reporter.h>
#include <gems/vfs.h>
#include <gems/vfs_font.h>
#include <gems/cached_font.h>
@ -72,6 +73,9 @@ struct Terminal::Main : Character_consumer
Color_palette _color_palette { };
Constructible<Attached_rom_dataspace> _clipboard_rom { };
Constructible<Expanding_reporter> _clipboard_reporter { };
void _handle_config();
Signal_handler<Main> _config_handler {
@ -82,6 +86,14 @@ struct Terminal::Main : Character_consumer
Framebuffer _framebuffer { _env, _config_handler };
Point _pointer { }; /* pointer positon in pixels */
bool _shift_pressed = false;
bool _selecting = false;
struct Paste_buffer { char buffer[READ_BUFFER_SIZE]; } _paste_buffer { };
typedef Pixel_rgb565 PT;
Constructible<Text_screen_surface<PT>> _text_screen_surface { };
@ -139,6 +151,9 @@ struct Terminal::Main : Character_consumer
Signal_handler<Main> _input_handler {
_env.ep(), *this, &Main::_handle_input };
void _report_clipboard_selection();
void _paste_clipboard_content();
Main(Env &env) : _env(env)
{
_timer .sigh(_flush_handler);
@ -170,6 +185,12 @@ void Terminal::Main::_handle_config()
_font.construct(_heap, _root_dir, cache_limit);
_clipboard_reporter.conditional(config.attribute_value("copy", false),
_env, "clipboard", "clipboard");
_clipboard_rom.conditional(config.attribute_value("paste", false),
_env, "clipboard");
/*
* Adapt terminal to font or framebuffer mode changes
*/
@ -252,6 +273,56 @@ void Terminal::Main::_handle_input()
{
_input.for_each_event([&] (Input::Event const &event) {
event.handle_absolute_motion([&] (int x, int y) {
_pointer = Point(x, y);
if (_shift_pressed) {
_text_screen_surface->pointer(_pointer);
_schedule_flush();
}
if (_selecting) {
_text_screen_surface->define_selection(_pointer);
_schedule_flush();
}
});
if (event.key_press(Input::KEY_LEFTSHIFT)) {
if (_clipboard_reporter.constructed()) {
_shift_pressed = true;
_text_screen_surface->clear_selection();
_text_screen_surface->pointer(_pointer);
_schedule_flush();
}
}
if (event.key_release(Input::KEY_LEFTSHIFT)) {
_shift_pressed = false;
_text_screen_surface->pointer(Point(-1, -1));
_schedule_flush();
}
if (event.key_press(Input::BTN_LEFT)) {
if (_shift_pressed) {
_selecting = true;
_text_screen_surface->start_selection(_pointer);
} else {
_text_screen_surface->clear_selection();
}
_schedule_flush();
}
if (event.key_release(Input::BTN_LEFT)) {
if (_selecting) {
_selecting = false;
_report_clipboard_selection();
}
}
if (event.key_press(Input::BTN_MIDDLE))
_paste_clipboard_content();
event.handle_press([&] (Input::Keycode, Codepoint codepoint) {
/* function-key unicodes */
@ -304,4 +375,56 @@ void Terminal::Main::_handle_input()
}
void Terminal::Main::_report_clipboard_selection()
{
if (!_clipboard_reporter.constructed())
return;
_clipboard_reporter->generate([&] (Xml_generator &xml) {
_text_screen_surface->for_each_selected_character([&] (Codepoint c) {
String<10> const utf8(c);
if (utf8.valid())
xml.append_sanitized(utf8.string(), utf8.length() - 1);
});
});
}
void Terminal::Main::_paste_clipboard_content()
{
if (!_clipboard_rom.constructed())
return;
_clipboard_rom->update();
_paste_buffer = { };
/* leave last byte as zero-termination in tact */
size_t const max_len = sizeof(_paste_buffer.buffer) - 1;
size_t const len =
_clipboard_rom->xml().decoded_content(_paste_buffer.buffer, max_len);
if (len == max_len) {
warning("clipboard content exceeds paste buffer");
return;
}
if (len >= (size_t)_read_buffer.avail_capacity()) {
warning("clipboard content exceeds read-buffer capacity");
return;
}
for (Utf8_ptr utf8(_paste_buffer.buffer); utf8.complete(); utf8 = utf8.next()) {
Codepoint const c = utf8.codepoint();
/* filter out control characters */
if (c.value < 32 && c.value != 10)
continue;
_read_buffer.add(c);
}
}
void Component::construct(Genode::Env &env) { static Terminal::Main main(env); }

View File

@ -91,6 +91,17 @@ class Terminal::Text_screen_surface
Point start() const { return Point(1, 1); }
bool valid() const { return columns*lines > 0; }
/**
* Return character position at given pixel coordinates
*/
Position position(Point p) const
{
if (char_width.value == 0 || char_height == 0)
return Position { };
return Position((p.x() << 8) / char_width.value, p.y() / char_height);
}
};
/**
@ -133,6 +144,29 @@ class Terminal::Text_screen_surface
Decoder _decoder { _character_screen };
struct Selection
{
Position start { };
Position end { };
bool defined = false;
bool selected(Position pos) const
{
return defined && pos.in_range(start, end);
}
template <typename FN>
void for_each_line(FN const &fn) const
{
for (int i = min(start.y, end.y); i <= max(start.y, end.y); i++)
fn(i);
}
} _selection { };
Position _pointer { -1, -1 };
public:
/**
@ -199,7 +233,20 @@ class Terminal::Text_screen_surface
Char_cell const cell = _cell_array.get_cell(column, line);
_font.apply_glyph(cell.codepoint(), [&] (Glyph_painter::Glyph const &glyph) {
Codepoint codepoint = cell.codepoint();
/* display absent codepoints as whitespace */
bool const codepoint_valid = (codepoint.value != 0);
bool const selected = _selection.selected(Position(column, line))
&& codepoint_valid;
bool const pointer = (_pointer == Position(column, line));
if (!codepoint_valid)
codepoint = Codepoint{' '};
_font.apply_glyph(codepoint, [&] (Glyph_painter::Glyph const &glyph) {
Color_palette::Highlighted const highlighted { cell.highlight() };
@ -216,6 +263,16 @@ class Terminal::Text_screen_surface
Color fg_color = _palette.foreground(fg_idx, highlighted);
Color bg_color = _palette.background(bg_idx, highlighted);
if (selected) {
bg_color = Color(180, 180, 180);
fg_color = Color( 50, 50, 50);
}
if (pointer) {
bg_color = Color(220, 220, 220);
fg_color = Color( 50, 50, 50);
}
if (cell.has_cursor()) {
fg_color = Color( 63, 63, 63);
bg_color = Color(255, 255, 255);
@ -271,6 +328,8 @@ class Terminal::Text_screen_surface
void apply_character(Character c)
{
clear_selection();
/* submit character to sequence decoder */
_decoder.insert(c);
}
@ -284,6 +343,110 @@ class Terminal::Text_screen_surface
* Return size in colums/rows
*/
Area size() const { return _geometry.size(); }
/**
* Set pointer position in pixels (to show the cursor)
*/
void pointer(Point pointer)
{
auto position_valid = [&] (Position pos) {
return pos.y >= 0 && pos.y < (int)_geometry.lines; };
/* update old position */
if (position_valid(_pointer))
_cell_array.mark_line_as_dirty(_pointer.y);
_pointer = _geometry.position(pointer);
/* update new position */
if (position_valid(_pointer))
_cell_array.mark_line_as_dirty(_pointer.y);
}
/**
* Set anchor point of selection
*
* \param pointer pointer position in pixels
*/
void start_selection(Point pointer)
{
if (_selection.defined)
clear_selection();
_selection.start = _geometry.position(pointer);
define_selection(pointer);
}
/**
* Set end position of current selection
*
* \param pointer pointer position in pixels
*/
void define_selection(Point pointer)
{
_selection.for_each_line([&] (int line) {
_cell_array.mark_line_as_dirty(line); });
_selection.end = _geometry.position(pointer);
_selection.defined = true;
_selection.for_each_line([&] (int line) {
_cell_array.mark_line_as_dirty(line); });
}
void clear_selection()
{
if (!_selection.defined)
return;
_selection.for_each_line([&] (int line) {
_cell_array.mark_line_as_dirty(line); });
_selection.defined = false;
}
template <typename FN>
void for_each_selected_character(FN const &fn) const
{
for (unsigned row = 0; row < _geometry.lines; row++) {
bool skip_remaining_chars_on_row = false;
for (unsigned column = 0; column < _geometry.columns; column++) {
if (skip_remaining_chars_on_row)
continue;
if (!_selection.selected(Position(column, row)))
continue;
Codepoint const c { _cell_array.get_cell(column, row).value };
if (c.value == 0) {
auto remaining_line_empty = [&] ()
{
for (unsigned i = column + 1; i < _geometry.columns; i++)
if (_cell_array.get_cell(i, row).value)
return false;
return true;
};
/* generate one line break at the end of a selected line */
if (remaining_line_empty()) {
fn(Codepoint{'\n'});
skip_remaining_chars_on_row = true;
} else {
fn(Codepoint{' '});
}
} else {
fn(c);
}
}
}
}
};
#endif /* _TEXT_SCREEN_SURFACE_H_ */

View File

@ -23,6 +23,7 @@
/* local includes */
#include <nitpicker.h>
#include <report_forwarder.h>
#include <rom_forwarder.h>
namespace Wm {
@ -110,6 +111,7 @@ struct Wm::Main
{ env.ep(), *this, &Main::handle_resize_request_update };
Report_forwarder _report_forwarder { env, heap };
Rom_forwarder _rom_forwarder { env, heap };
Main(Genode::Env &env) : env(env)
{

View File

@ -1,5 +1,5 @@
/*
* \brief Report service for intercepting shape reports
* \brief Report service for intercepting shape and clipboard reports
* \author Norman Feske
* \date 2019-02-18
*
@ -7,6 +7,9 @@
* policy to an application's shape report as done for the application's
* 'Nitpicker' session. This consistency is needed by the pointer to correlate
* the currently hovered nitpicker session with the reported shapes.
* Analogously, clipboard reports can be routed through the window
* manager to support the clipboard component with associating its clients
* with nitpicker's reported focus.
*/
/*

View File

@ -0,0 +1,96 @@
/*
* \brief ROM service for intercepting clipboard ROMs
* \author Norman Feske
* \date 2019-06-26
*
* This ROM service can be used as proxy for clipboard ROMs to ensure the
* consistency of the client labels appearing at the clipboard component
* with the label of the currently focused nitpicker client.
*/
/*
* Copyright (C) 2019 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _ROM_FORWARDER_H_
#define _ROM_FORWARDER_H_
/* Genode includes */
#include <root/component.h>
#include <rom_session/connection.h>
namespace Wm { struct Rom_forwarder; }
struct Wm::Rom_forwarder
{
struct Session : Genode::Rpc_object<Genode::Rom_session>
{
Genode::Env &_env;
Genode::Rom_connection _connection;
Session(Genode::Env &env, Genode::Session_label const &label)
: _env(env), _connection(env, label.string())
{ _env.ep().manage(*this); }
~Session() { _env.ep().dissolve(*this); }
void upgrade(Genode::Session::Resources const &resources)
{
_connection.upgrade(resources);
}
/***************************
** Rom_session interface **
***************************/
Genode::Rom_dataspace_capability dataspace() override
{
return _connection.dataspace();
}
bool update() override
{
return _connection.update();
}
void sigh(Signal_context_capability sigh) override
{
_connection.sigh(sigh);
}
};
struct Root : Genode::Root_component<Session>
{
Genode::Env &_env;
Genode::Allocator &_alloc;
Session *_create_session(char const *args) override
{
return new (md_alloc()) Session(_env, Genode::label_from_args(args));
}
void _upgrade_session(Session *session, const char *args) override
{
session->upgrade(Genode::session_resources_from_args(args));
}
Root(Genode::Env &env, Genode::Allocator &alloc)
:
Genode::Root_component<Session>(env.ep(), alloc),
_env(env), _alloc(alloc)
{
_env.parent().announce(env.ep().manage(*this));
}
} _root;
Rom_forwarder(Genode::Env &env, Genode::Allocator &alloc)
: _root(env, alloc) { }
};
#endif /* _ROM_FORWARDER_H_ */

View File

@ -4,6 +4,8 @@
<file_system/>
<nitpicker/>
<report label="shape"/>
<report label="clipboard"/>
<rom label="clipboard"/>
<timer/>
</requires>

View File

@ -1,4 +1,4 @@
<config>
<config clipboard="yes">
<vfs>
<dir name="dev">
<log/>

View File

@ -4,7 +4,7 @@
# \date 2016-06-05
#
if {[have_spec linux] || [have_spec imx7d_sabre] ||
if {[have_spec linux] || [have_spec rpi3] ||
[expr [have_spec imx53] && [have_spec trustzone]]} {
puts "Run script does not support this platform."
exit 0

View File

@ -9,14 +9,14 @@ if {[have_spec odroid_xu] || [have_spec zynq]} {
exit 0
}
# use SD on ARM
set use_sd_card_drv [expr [have_spec pbxa9]]
# use SD on Qemu/pbxa9
set use_sd_card_drv [expr [have_include "power_on/qemu"] && [have_spec pbxa9]]
# use AHCI on x86
set use_ahci [expr [have_spec x86] && ![have_spec linux]]
# use ram_block on Linux
set use_ram_block [have_spec linux]
# use ram_block on Linux and Qemu/rpi3
set use_ram_block [expr [have_spec linux] || [expr [have_include "power_on/qemu"] && [have_spec rpi3]]]
if {[catch { exec which $mkfs_cmd } ]} {
puts stderr "Error: $mkfs_cmd not installed, aborting test"; exit }

View File

@ -22,7 +22,7 @@
if {[expr [have_spec linux]] ||
[expr [have_spec imx53] && [have_spec trustzone]] ||
[expr [have_spec imx7d_sabre]] ||
[have_spec rpi3] ||
[expr [have_spec riscv]]} {
puts "\n Run script is not supported on this platform. \n"; exit 0 }

View File

@ -70,7 +70,9 @@ set config {
<start name="wm" caps="1000">
<resource name="RAM" quantum="32M"/>
<binary name="init"/>
<provides> <service name="Nitpicker"/> </provides>
<provides>
<service name="Nitpicker"/> <service name="Report"/> <service name="ROM"/>
</provides>
<route>
<service name="ROM" label="config"> <parent label="wm.config"/> </service>
<service name="Nitpicker"> <child name="nitpicker"/> </service>

View File

@ -3,6 +3,11 @@ if {![have_include power_on/qemu]} {
exit 0
}
if {[have_spec rpi3]} {
puts "\n Run script is not supported on this platform. \n";
exit 0
}
create_boot_directory
import_from_depot [depot_user]/src/[base_src] \

View File

@ -187,7 +187,7 @@ proc qt5_start_nodes { feature_arg } {
<start name="wm" caps="250">
<resource name="RAM" quantum="8M"/>
<provides>
<service name="Nitpicker"/> <service name="Report"/>
<service name="Nitpicker"/> <service name="Report"/> <service name="ROM"/>
</provides>
<config>
<policy label_prefix="decorator" role="decorator"/>

View File

@ -1,5 +1,5 @@
if {![have_spec 64bit]} {
puts "\nSolo5 requires a 64bit architecture\n"
if {![have_spec x86_64]} {
puts "\nTest requires x86_64\n"
exit 0
}

View File

@ -1,5 +1,5 @@
if {![have_spec x86_64]} {
puts "\nSolo5 requires a 64bit architecture\n"
puts "\nTest requires x86_64\n"
exit 0
}

View File

@ -1,5 +1,5 @@
if {![have_spec 64bit]} {
puts "\nSolo5 requires a 64bit architecture\n"
if {![have_spec x86_64]} {
puts "\nTest requires x86_64\n"
exit 0
}

View File

@ -20,4 +20,5 @@
-#define MB_CUR_MAX_L(x) ((size_t)___mb_cur_max_l(x))
+/* ASCII only */
+#define MB_CUR_MAX_L(x) 1

View File

@ -0,0 +1,63 @@
Prevent the use of the hidden attribute for symbols. In particular,
the attribute must not be applied to '__libc'-prefixed symbols to allow
overwriting the dummies defined in dummies.cc by other non-weak
implementations such as those in 'libc_noux.lib.so'.
This attribute is applied inconsistently in
libc/lib/libc/include/libc_private.h anyway.
Also, force i386 to call __libc_sigprocmask via PLT to prevent
R_386_PC32 relocations, which had to change the text segment. Other
architectures do this automatically.
--- src/lib/libc/sys/sys/cdefs.h
+++ src/lib/libc/sys/sys/cdefs.h
@@ -447,7 +447,7 @@
#if __GNUC_PREREQ__(4, 0)
#define __null_sentinel __attribute__((__sentinel__))
#define __exported __attribute__((__visibility__("default")))
-#define __hidden __attribute__((__visibility__("hidden")))
+#define __hidden
#else
#define __null_sentinel
#define __exported
--- src/lib/libc/lib/libc/i386/gen/setjmp.S
+++ src/lib/libc/lib/libc/i386/gen/setjmp.S
@@ -54,7 +54,7 @@
pushl %eax /* (sigset_t*)oset */
pushl $0 /* (sigset_t*)set */
pushl $1 /* SIG_BLOCK */
- call __libc_sigprocmask
+ call __i386_libc_sigprocmask
addl $12,%esp
movl 4(%esp),%ecx
movl 0(%esp),%edx
@@ -76,7 +76,7 @@
leal 28(%edx), %eax
pushl %eax /* (sigset_t*)set */
pushl $3 /* SIG_SETMASK */
- call __libc_sigprocmask
+ call __i386_libc_sigprocmask
addl $12,%esp
movl 4(%esp),%edx
movl 8(%esp),%eax
--- src/lib/libc/lib/libc/i386/gen/sigsetjmp.S
+++ src/lib/libc/lib/libc/i386/gen/sigsetjmp.S
@@ -63,7 +63,7 @@
pushl %eax /* (sigset_t*)oset */
pushl $0 /* (sigset_t*)set */
pushl $1 /* SIG_BLOCK */
- call __libc_sigprocmask
+ call __i386_libc_sigprocmask
addl $12,%esp
movl 4(%esp),%ecx
2: movl 0(%esp),%edx
@@ -87,7 +87,7 @@
leal 28(%edx), %eax
pushl %eax /* (sigset_t*)set */
pushl $3 /* SIG_SETMASK */
- call __libc_sigprocmask
+ call __i386_libc_sigprocmask
addl $12,%esp
movl 4(%esp),%edx
2: movl 8(%esp),%eax

View File

@ -55,6 +55,14 @@ int __libc_sigprocmask(int how, const sigset_t *set, sigset_t *old) {
return sigprocmask(how, set, old); }
/* wrapper from text-relocated i386-assembler call to PLT call */
extern "C" int __i386_libc_sigprocmask(int how, const sigset_t *set, sigset_t *old) __attribute__((visibility("hidden")));
extern "C" int __i386_libc_sigprocmask(int how, const sigset_t *set, sigset_t *old)
{
return __libc_sigprocmask(how, set, old);
}
extern "C" __attribute__((weak))
pid_t wait4(pid_t, int *, int, struct rusage *)
{

View File

@ -20,7 +20,7 @@
struct Char_cell
{
Genode::uint16_t value { ' ' };
Genode::uint16_t value { 0 };
unsigned char attr;
unsigned char color;

View File

@ -76,6 +76,23 @@ struct Terminal::Position
bool operator != (Position const &pos) const {
return (pos.x != x) || (pos.y != y); }
bool operator >= (Position const &other) const
{
if (y > other.y)
return true;
if (y == other.y && x >= other.x)
return true;
return false;
}
bool in_range(Position start, Position end) const
{
return (end >= start) ? *this >= start && end >= *this
: *this >= end && start >= *this;
}
/**
* Return true if position lies within the specified boundaries
*/

View File

@ -1,6 +1,7 @@
if {[have_spec odroid_xu] ||
[have_spec imx7d_sabre] ||
[have_spec imx6q_sabrelite] ||
[have_spec rpi3] ||
[have_spec zynq] ||
[have_spec imx53] && [have_spec foc]} {
puts "\n Run script is not supported on this platform. \n";

View File

@ -1,4 +1,5 @@
if {[have_spec foc] || [have_spec odroid_xu] || [have_spec linux] || [have_spec imx7d_sabre] ||
if {[have_spec foc] || [have_spec odroid_xu] || [have_spec linux] ||
[have_spec rpi3] ||
[expr [have_spec imx53] && [have_spec trustzone]]} {
puts "Run script is not supported on this platform."
exit 0

View File

@ -1,5 +1,6 @@
if {![have_include power_on/qemu] ||
[have_spec foc] ||
[have_spec rpi3] ||
[expr [have_spec imx53] && [have_spec trustzone]]} {
puts "Run script is not supported on this platform."

View File

@ -1,4 +1,5 @@
if {[have_spec foc] || [have_spec linux] || [have_spec imx7d_sabre] ||
if {[have_spec foc] || [have_spec linux] ||
[have_spec rpi3] ||
[expr [have_spec imx53] && [have_spec trustzone]]} {
puts "Run script is not supported on this platform."
exit 0

View File

@ -1,4 +1,5 @@
if {[have_spec foc] || [have_spec odroid_xu] || [have_spec linux] || [have_spec imx7d_sabre] ||
if {[have_spec foc] || [have_spec odroid_xu] || [have_spec linux] ||
[have_spec rpi3] ||
[expr [have_spec imx53] && [have_spec trustzone]]} {
puts "Run script is not supported on this platform."
exit 0

View File

@ -223,7 +223,14 @@ foreach rom [content_rom_modules] {
# raw-archive content is installed directly into [run_dir]/genode
if {![rom_module_from_raw_archive $rom]} {
lappend boot_modules $rom }
lappend boot_modules $rom
}
# handle vfs plugin shared-object targets
if {[regexp "^vfs_(.+).lib.so$" $rom dummy plugin]} {
lappend build_targets lib/vfs/$plugin
continue
}
if {[info exists src_sub_dir($rom)]} {
lappend build_targets $src_sub_dir($rom)

View File

@ -76,15 +76,11 @@ struct Clipboard::Main : Rom::Module::Read_policy, Rom::Module::Write_policy
Genode::Attached_rom_dataspace _config { _env, "config" };
bool _verbose_config()
{
char const *attr = "verbose";
return _config.xml().attribute_value(attr, false);
}
bool verbose { _verbose_config() };
bool _verbose = false;
bool _match_labels = false;
typedef Genode::String<100> Domain;
typedef Genode::String<100> Label;
Genode::Attached_rom_dataspace _focus_ds { _env, "focus" };
@ -94,6 +90,7 @@ struct Clipboard::Main : Rom::Module::Read_policy, Rom::Module::Write_policy
{ _env.ep(), *this, &Main::_handle_focus };
Domain _focused_domain { };
Label _focused_label { };
/**
* Handle configuration changes
@ -101,7 +98,8 @@ struct Clipboard::Main : Rom::Module::Read_policy, Rom::Module::Write_policy
void _handle_config()
{
_config.update();
verbose = _verbose_config();
_verbose = _config.xml().attribute_value("verbose", false);
_match_labels = _config.xml().attribute_value("match_labels", false);
}
/**
@ -114,14 +112,14 @@ struct Clipboard::Main : Rom::Module::Read_policy, Rom::Module::Write_policy
_focus_ds.update();
_focused_domain = Domain();
_focused_label = Label();
try {
Genode::Xml_node focus(_focus_ds.local_addr<char>(), _focus_ds.size());
Genode::Xml_node const focus = _focus_ds.xml();
if (focus.attribute_value("active", false))
_focused_domain = focus.attribute_value("domain", Domain());
} catch (...) { }
if (focus.attribute_value("active", false)) {
_focused_domain = focus.attribute_value("domain", Domain());
_focused_label = focus.attribute_value("label", Label());
}
}
Domain _domain(Genode::Session_label const &label) const
@ -135,20 +133,30 @@ struct Clipboard::Main : Rom::Module::Read_policy, Rom::Module::Write_policy
return Domain();
}
Domain _domain(Rom::Reader const &reader) const
Label _label(Rom::Reader const &reader) const
{
Rom::Session_component const &rom_session =
static_cast<Rom::Session_component const &>(reader);
return _domain(rom_session.label());
return rom_session.label();
}
Domain _domain(Rom::Writer const &writer) const
Domain _domain(Rom::Reader const &reader) const
{
return _domain(_label(reader));
}
Label _label(Rom::Writer const &writer) const
{
Report::Session_component const &report_session =
static_cast<Report::Session_component const &>(writer);
return _domain(report_session.label());
return report_session.label();
}
Domain _domain(Rom::Writer const &writer) const
{
return _domain(_label(writer));
}
bool _flow_defined(Domain const &from, Domain const &to) const
@ -175,6 +183,39 @@ struct Clipboard::Main : Rom::Module::Read_policy, Rom::Module::Write_policy
return result;
}
bool _client_label_matches_focus(Genode::Session_label const &label) const
{
using namespace Genode;
/*
* The client label has the suffix " -> clipboard". Strip off this
* part to make the label comparable with the label of the client's
* nitpicker session (which has of course no such suffix).
*/
char const *suffix = " -> clipboard";
size_t const suffix_len = strlen(suffix);
if (label.length() < suffix_len + 1)
return false;
size_t const truncated_label_len = label.length() - suffix_len - 1;
Session_label const
truncated_label(Cstring(label.string(), truncated_label_len));
/*
* We accept any subsystem of the client to have the nitpicker focus.
* E.g., a multi-window application may have multiple nitpicker
* sessions, one for each window. The labels of all of those nitpicker
* session share the first part with application's clipboard label.
*/
bool const focus_lies_in_client_subsystem =
!strcmp(_focused_label.string(), truncated_label.string(),
truncated_label_len);
return focus_lies_in_client_subsystem;
}
/**
* Rom::Module::Read_policy interface
*/
@ -185,6 +226,9 @@ struct Clipboard::Main : Rom::Module::Read_policy, Rom::Module::Write_policy
Domain const from_domain = _domain(writer);
Domain const to_domain = _domain(reader);
if (_match_labels && !_client_label_matches_focus(_label(reader)))
return false;
if (from_domain == to_domain)
return true;
@ -194,14 +238,16 @@ struct Clipboard::Main : Rom::Module::Read_policy, Rom::Module::Write_policy
return false;
}
/**
* Rom::Module::Write_policy interface
*/
bool write_permitted(Rom::Module const &module,
Rom::Writer const &writer) const override
{
if (_focused_domain.valid() && _domain(writer) == _focused_domain)
bool const domain_matches =
_focused_domain.valid() && _domain(writer) == _focused_domain;
if ((!_match_labels || _client_label_matches_focus(_label(writer))) && domain_matches)
return true;
warning("unexpected attempt by '", writer.label(), "' "
@ -212,11 +258,13 @@ struct Clipboard::Main : Rom::Module::Read_policy, Rom::Module::Write_policy
Rom::Registry _rom_registry { _env.ram(), _env.rm(), *this, *this };
Report::Root report_root = { _env, _sliced_heap, _rom_registry, verbose };
Report::Root report_root = { _env, _sliced_heap, _rom_registry, _verbose };
Rom ::Root rom_root = { _env, _sliced_heap, _rom_registry };
Main(Genode::Env &env) : _env(env)
{
_config.sigh(_config_handler);
_handle_config();
_focus_ds.sigh(_focus_handler);
_handle_focus();

View File

@ -1,61 +0,0 @@
The new _trace_fs_ server provides access to a trace session by providing a
file-system session as front end. Combined with Noux, it allows for the
interactive exploration and tracing of Genode's process tree using
traditional Unix tools.
Each trace subject is represented by a directory ('thread_name.subject') that
contains specific files, which are used to control the tracing process of the
thread as well as storing the content of its trace buffer:
:'enable': The tracing of a thread is activated if there is a valid policy
installed and the intend to trace the subject was made clear by writing '1'
to the 'enable' file. The tracing of a thread may be deactivated by writing a
'0' to this file.
:'policy': A policy may be changed by overwriting the currently used one in the
'policy' file. In this case, the old policy is replaced by the new one and
automatically used by the framework.
:'buffer_size': Writing a value to the 'buffer_size' file changes the size of
the trace buffer. This value is evaluated only when reactivating the tracing
of the thread.
:'events': The trace-buffer contents may be accessed by reading from the
'events' file. New trace events are appended to this file.
:'active': Reading the file will return whether the tracing is active (1) or
not (0).
:'cleanup': Nodes of untraced subjects are kept as long as they do not change
their tracing state to dead. Dead untraced nodes are automatically removed
from the file system. Subjects that were traced before and are now untraced
can be removed by writing '1' to the 'cleanup' file.
To use the trace_fs, a configuration similar to the following may be used:
! <start name="trace_fs">
! <resource name="RAM" quantum="128M"/>
! <provides><service name="File_system"/></provides>
! <config>
! <policy label_prefix="noux -> trace"
! interval="1000"
! subject_limit="512"
! trace_quota="64M" />
! </config>
! </start>
:'interval': sets the period the Trace_session is polled. The
time is given in milliseconds.
:'subject_limit': specifies how many trace subjects should by acquired at
max when the Trace_session is polled.
:'trace_quota': is the amount of quota the trace_fs should use for the
Trace_session connection. The remaining amount of RAM quota will be used
for the actual nodes of the file system and the 'policy' as well as the
'events' files.
In addition, there are 'buffer_size' and 'buffer_size_limit' that define
the initial and the upper limit of the size of a trace buffer.
A ready-to-use run script can by found in 'ports/run/noux_trace_fs.run'.

View File

@ -1,134 +0,0 @@
/*
* \brief Buffer class
* \author Josef Soentgen
* \date 2014-01-15
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _BUFFER_H_
#define _BUFFER_H_
/* Genode includes */
#include <util/string.h>
namespace Util {
typedef Genode::size_t size_t;
/**
* Buffer merely wrapps a simple char array
*/
template <size_t CAPACITY>
class Buffer
{
public:
class Out_of_range { };
private:
char _buf[CAPACITY];
size_t _length;
public:
static size_t capacity() { return CAPACITY; }
Buffer() : _length(0) { }
Buffer(char const *s)
:
_length(Genode::min(Genode::strlen(s) + 1, CAPACITY))
{
Genode::strncpy(_buf, s, _length);
}
char const *data() const { return (_buf[_length -1 ] == '\0') ? _buf : ""; }
char *data() { return _buf; }
size_t length() const { return _length; }
char & operator[](size_t i)
{
if (i >= CAPACITY)
throw Out_of_range();
return _buf[i];
}
void replace(char p, char c)
{
char *s = _buf;
for (; *s; s++) {
if (*s == p)
*s = c;
}
}
};
/**
* This class walks along a label and returns the next element on request
*/
class Label_walker
{
private:
Buffer<64> _buffer;
char const *_label;
char const *_next()
{
size_t i = 0;
for (; *_label && (i < _buffer.capacity()); _label++, i++) {
/* check seperator */
if ((*_label == ' ') &&
(*(_label + 1) == '-') &&
(*(_label + 2) == '>') &&
(*(_label + 3) == ' '))
break;
_buffer[i] = *_label;
}
_buffer[i] = '\0';
/* sanatize the element */
_buffer.replace('/', '_');
/* omit seperator */
if (*_label)
_label += 4;
return _label;
}
public:
Label_walker(char const *label) : _label(label) { }
/**
* Walk to the next element of the label
*
* \return pointer to the remaing part of the label
*/
char const *next() { return _next(); }
/**
* Get current element of the label
*
* \return pointer to current element
*/
char const *element() { return _buffer.data(); }
};
}
#endif /* _BUFFER_H_ */

View File

@ -1,441 +0,0 @@
/*
* \brief Data structure for storing sparse files in RAM
* \author Norman Feske
* \date 2012-04-18
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _CHUNK_H_
#define _CHUNK_H_
/* Genode includes */
#include <util/noncopyable.h>
#include <base/allocator.h>
#include <util/string.h>
#include <file_system_session/file_system_session.h>
namespace File_system {
using namespace Genode;
/**
* Common base class of both 'Chunk' and 'Chunk_index'
*/
class Chunk_base : Noncopyable
{
public:
class Index_out_of_range { };
protected:
seek_off_t const _base_offset;
size_t _num_entries; /* corresponds to last used entry */
/**
* Test if specified range lies within the chunk
*/
void assert_valid_range(seek_off_t start, size_t len,
file_size_t chunk_size) const
{
if (zero()) return;
if (start < _base_offset)
throw Index_out_of_range();
if (start + len > _base_offset + chunk_size)
throw Index_out_of_range();
}
Chunk_base(seek_off_t base_offset)
: _base_offset(base_offset), _num_entries(0) { }
/**
* Construct zero chunk
*
* A zero chunk is a chunk that cannot be written to. When reading
* from it, it returns zeros. Because there is a single zero chunk
* for each chunk type, the base offset is meaningless. We use a
* base offset of ~0 as marker to identify zero chunks.
*/
Chunk_base() : _base_offset(~0L), _num_entries(0) { }
public:
/**
* Return absolute base offset of chunk in bytes
*/
seek_off_t base_offset() const { return _base_offset; }
/**
* Return true if chunk is a read-only zero chunk
*/
bool zero() const { return _base_offset == (seek_off_t)(~0L); }
/**
* Return true if chunk has no allocated sub chunks
*/
bool empty() const { return _num_entries == 0; }
};
/**
* Chunk of bytes used as leaf in hierarchy of chunk indices
*/
template <unsigned CHUNK_SIZE>
class Chunk : public Chunk_base
{
private:
char _data[CHUNK_SIZE];
public:
enum { SIZE = CHUNK_SIZE };
/**
* Construct byte chunk
*
* \param base_offset absolute offset of chunk in bytes
*
* The first argument is unused. Its mere purpose is to make the
* signature of the constructor compatible to the constructor
* of 'Chunk_index'.
*/
Chunk(Allocator &, seek_off_t base_offset)
:
Chunk_base(base_offset)
{
memset(_data, 0, CHUNK_SIZE);
}
/**
* Construct zero chunk
*/
Chunk() { }
/**
* Return number of used entries
*
* The returned value corresponds to the index of the last used
* entry + 1. It does not correlate to the number of actually
* allocated entries (there may be ranges of zero blocks).
*/
file_size_t used_size() const { return _num_entries; }
void write(char const *src, size_t len, seek_off_t seek_offset)
{
assert_valid_range(seek_offset, len, SIZE);
/* offset relative to this chunk */
seek_off_t const local_offset = seek_offset - base_offset();
memcpy(&_data[local_offset], src, len);
_num_entries = max(_num_entries, local_offset + len);
}
void read(char *dst, size_t len, seek_off_t seek_offset) const
{
assert_valid_range(seek_offset, len, SIZE);
memcpy(dst, &_data[seek_offset - base_offset()], len);
}
void truncate(file_size_t size)
{
assert_valid_range(size, 0, SIZE);
/*
* Offset of the first free position (relative to the beginning
* this chunk).
*/
seek_off_t const local_offset = size - base_offset();
if (local_offset >= _num_entries)
return;
memset(&_data[local_offset], 0, _num_entries - local_offset);
_num_entries = local_offset;
}
};
template <unsigned NUM_ENTRIES, typename ENTRY_TYPE>
class Chunk_index : public Chunk_base
{
public:
typedef ENTRY_TYPE Entry;
enum { ENTRY_SIZE = ENTRY_TYPE::SIZE,
SIZE = ENTRY_SIZE*NUM_ENTRIES };
private:
Allocator &_alloc;
Entry * _entries[NUM_ENTRIES];
/**
* Return instance of a zero sub chunk
*/
static Entry const &_zero_chunk()
{
static Entry zero_chunk;
return zero_chunk;
}
/**
* Return sub chunk at given index
*
* If there is no sub chunk at the specified index, this function
* transparently allocates one. Hence, the returned sub chunk
* is ready to be written to.
*/
Entry &_entry_for_writing(unsigned index)
{
if (index >= NUM_ENTRIES)
throw Index_out_of_range();
if (_entries[index])
return *_entries[index];
seek_off_t entry_offset = base_offset() + index*ENTRY_SIZE;
_entries[index] = new (&_alloc) Entry(_alloc, entry_offset);
_num_entries = max(_num_entries, index + 1);
return *_entries[index];
}
/**
* Return sub chunk at given index (for reading only)
*
* This function transparently provides a zero sub chunk for any
* index that is not populated by a real chunk.
*/
Entry const &_entry_for_reading(unsigned index) const
{
if (index >= NUM_ENTRIES)
throw Index_out_of_range();
if (_entries[index])
return *_entries[index];
return _zero_chunk();
}
/**
* Return index of entry located at specified byte offset
*
* The caller of this function must make sure that the offset
* parameter is within the bounds of the chunk.
*/
unsigned _index_by_offset(seek_off_t offset) const
{
return (offset - base_offset()) / ENTRY_SIZE;
}
/**
* Apply operation 'func' to a range of entries
*/
template <typename THIS, typename DATA, typename FUNC>
static void _range_op(THIS &obj, DATA *data, size_t len,
seek_off_t seek_offset, FUNC const &func)
{
/*
* Depending on whether this function is called for reading
* (const function) or writing (non-const function), the
* operand type is const or non-const Entry. The correct type
* is embedded as a trait in the 'FUNC' functor type.
*/
typedef typename FUNC::Entry Const_qualified_entry;
obj.assert_valid_range(seek_offset, len, SIZE);
while (len > 0) {
unsigned const index = obj._index_by_offset(seek_offset);
Const_qualified_entry &entry = FUNC::lookup(obj, index);
/*
* Calculate byte offset relative to the chunk
*
* We cannot use 'entry.base_offset()' for this calculation
* because in the const case, the lookup might return a
* zero chunk, which has no defined base offset. Therefore,
* we calculate the base offset via index*ENTRY_SIZE.
*/
seek_off_t const local_seek_offset =
seek_offset - obj.base_offset() - index*ENTRY_SIZE;
/* available capacity at 'entry' starting at seek offset */
seek_off_t const capacity = ENTRY_SIZE - local_seek_offset;
seek_off_t const curr_len = min(len, capacity);
/* apply functor (read or write) to entry */
func(entry, data, curr_len, seek_offset);
/* advance to next entry */
len -= curr_len;
data += curr_len;
seek_offset += curr_len;
}
}
struct Write_func
{
typedef ENTRY_TYPE Entry;
static Entry &lookup(Chunk_index &chunk, unsigned i) {
return chunk._entry_for_writing(i); }
void operator () (Entry &entry, char const *src, size_t len,
seek_off_t seek_offset) const
{
entry.write(src, len, seek_offset);
}
};
struct Read_func
{
typedef ENTRY_TYPE const Entry;
static Entry &lookup(Chunk_index const &chunk, unsigned i) {
return chunk._entry_for_reading(i); }
void operator () (Entry &entry, char *dst, size_t len,
seek_off_t seek_offset) const
{
if (entry.zero())
memset(dst, 0, len);
else
entry.read(dst, len, seek_offset);
}
};
void _init_entries()
{
for (unsigned i = 0; i < NUM_ENTRIES; i++)
_entries[i] = 0;
}
void _destroy_entry(unsigned i)
{
if (_entries[i] && (i < _num_entries)) {
destroy(&_alloc, _entries[i]);
_entries[i] = 0;
}
}
public:
/**
* Constructor
*
* \param alloc allocator to use for allocating sub-chunk
* indices and chunks
* \param base_offset absolute offset of the chunk in bytes
*/
Chunk_index(Allocator &alloc, seek_off_t base_offset)
: Chunk_base(base_offset), _alloc(alloc) { _init_entries(); }
/**
* Construct zero chunk
*/
Chunk_index() : _alloc(*(Allocator *)0) { }
/**
* Destructor
*/
~Chunk_index()
{
for (unsigned i = 0; i < NUM_ENTRIES; i++)
_destroy_entry(i);
}
/**
* Return size of chunk in bytes
*
* The returned value corresponds to the position after the highest
* offset that was written to.
*/
file_size_t used_size() const
{
if (_num_entries == 0)
return 0;
/* size of entries that lie completely within the used range */
file_size_t const size_whole_entries = ENTRY_SIZE*(_num_entries - 1);
Entry *last_entry = _entries[_num_entries - 1];
if (!last_entry)
return size_whole_entries;
return size_whole_entries + last_entry->used_size();
}
/**
* Write data to chunk
*/
void write(char const *src, size_t len, seek_off_t seek_offset)
{
_range_op(*this, src, len, seek_offset, Write_func());
}
/**
* Read data from chunk
*/
void read(char *dst, size_t len, seek_off_t seek_offset) const
{
_range_op(*this, dst, len, seek_offset, Read_func());
}
/**
* Truncate chunk to specified size in bytes
*
* This function can be used to shrink a chunk only. Specifying a
* 'size' larger than 'used_size' has no effect. The value returned
* by 'used_size' refers always to the position of the last byte
* written to the chunk.
*/
void truncate(file_size_t size)
{
unsigned const trunc_index = _index_by_offset(size);
if (trunc_index >= _num_entries)
return;
for (unsigned i = trunc_index + 1; i < _num_entries; i++)
_destroy_entry(i);
/* traverse into sub chunks */
if (_entries[trunc_index])
_entries[trunc_index]->truncate(size);
_num_entries = trunc_index + 1;
/*
* If the truncated at a chunk boundary, we can release the
* empty trailing chunk at 'trunc_index'.
*/
if (_entries[trunc_index] && _entries[trunc_index]->empty()) {
_destroy_entry(trunc_index);
_num_entries--;
}
}
};
};
#endif /* _CHUNK_H_ */

View File

@ -1,222 +0,0 @@
/*
* \brief File-system directory node
* \author Norman Feske
* \date 2012-04-11
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DIRECTORY_H_
#define _DIRECTORY_H_
/* Genode includes */
#include <file_system/util.h>
/* local includes */
#include <node.h>
#include <file.h>
#include <symlink.h>
namespace Trace_fs {
class Directory;
}
class Trace_fs::Directory : public Node
{
private:
List<Node> _entries;
size_t _num_entries;
public:
Directory(char const *name) : _num_entries(0) { Node::name(name); }
/**
* Check if the directory has the specified subnode
*
* \param name name of the searched subnode
*
* \return true if the subnode was found, either false
*/
bool has_sub_node_unsynchronized(char const *name) const
{
Node const *sub_node = _entries.first();
for (; sub_node; sub_node = sub_node->next())
if (strcmp(sub_node->name(), name) == 0)
return true;
return false;
}
/**
* Add node to the list of subnodes
*
* \param pointer to node
*/
void adopt_unsynchronized(Node *node)
{
/*
* XXX inc ref counter
*/
_entries.insert(node);
_num_entries++;
mark_as_updated();
}
/**
* Remove the node from the list of subnodes
*
* \param node pointer to node
*/
void discard_unsynchronized(Node *node)
{
_entries.remove(node);
_num_entries--;
mark_as_updated();
}
/**
* Lookup node which belongs to the specified path
*
* \param path path to lookup
* \param return_parent if true return parent node, otherwise
* actual path node
*
* \return node node founc
* \throws Lookup_failed
*/
Node *lookup(char const *path, bool return_parent = false) override
{
if (strcmp(path, "") == 0) {
return this;
}
if (!path || path[0] == '/')
throw Lookup_failed();
/* find first path delimiter */
unsigned i = 0;
for (; path[i] && path[i] != '/'; i++);
/*
* If no path delimiter was found, we are the parent of the
* specified path.
*/
if (path[i] == 0 && return_parent) {
return this;
}
/*
* The offset 'i' corresponds to the end of the first path
* element, which can be either the end of the string or the
* first '/' character.
*/
/* try to find entry that matches the first path element */
Node *sub_node = _entries.first();
for (; sub_node; sub_node = sub_node->next())
if ((strlen(sub_node->name()) == i) &&
(strcmp(sub_node->name(), path, i) == 0))
break;
if (!sub_node)
throw Lookup_failed();
if (!contains_path_delimiter(path)) {
/*
* Because 'path' is a basename that corresponds to an
* existing sub_node, we have found what we were looking
* for.
*/
return sub_node;
}
/*
* As 'path' contains one or more path delimiters, traverse
* into the sub directory names after the first path element.
*/
/*
* We cannot traverse into anything other than a directory.
*
* XXX we might follow symlinks here
*/
Directory *sub_dir = dynamic_cast<Directory *>(sub_node);
if (!sub_dir)
throw Lookup_failed();
return sub_dir->lookup(path + i + 1, return_parent);
}
/**
* Return number of subnodes
*/
size_t num_entries() const { return _num_entries; }
/********************
** Node interface **
********************/
size_t read(char *dst, size_t len, seek_off_t seek_offset)
{
if (len < sizeof(Directory_entry)) {
Genode::error("read buffer too small for directory entry");
return 0;
}
seek_off_t index = seek_offset / sizeof(Directory_entry);
if (seek_offset % sizeof(Directory_entry)) {
Genode::error("seek offset not alighed to sizeof(Directory_entry)");
return 0;
}
/* find list element */
Node *node = _entries.first();
for (unsigned i = 0; i < index && node; node = node->next(), i++);
/* index out of range */
if (!node)
return 0;
Directory_entry *e = (Directory_entry *)(dst);
if (dynamic_cast<File *>(node)) e->type = Directory_entry::TYPE_FILE;
if (dynamic_cast<Directory *>(node)) e->type = Directory_entry::TYPE_DIRECTORY;
if (dynamic_cast<Symlink *>(node)) e->type = Directory_entry::TYPE_SYMLINK;
strncpy(e->name, node->name(), sizeof(e->name));
return sizeof(Directory_entry);
}
size_t write(char const *src, size_t len, seek_off_t seek_offset)
{
/* writing to directory nodes is not supported */
return 0;
}
Status status() const
{
Status s;
s.inode = inode();
s.size = _num_entries * sizeof (Directory_entry);
s.mode = File_system::Status::MODE_DIRECTORY;
return s;
}
};
#endif /* _DIRECTORY_H_ */

View File

@ -1,220 +0,0 @@
/*
* \brief File node
* \author Norman Feske
* \author Josef Soentgen
* \date 2012-04-11
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _FILE_H_
#define _FILE_H_
/* Genode includes */
#include <base/allocator.h>
#include <base/trace/types.h>
/* local includes */
#include <node.h>
#include <chunk.h>
namespace Trace_fs {
class Changeable_content;
class File;
class Buffered_file;
}
/**
*
*
*/
class Trace_fs::Changeable_content
{
protected:
/**
* This member is used to communicate the state and
* must be set true by classes using this class in case
* the content has changed.
*/
bool _changed;
/**
* This method is called when the content change is
* acknowledged. It may be overriden by any class using
* this particular class.
*/
virtual void _refresh_content() { }
public:
Changeable_content() : _changed(false) { }
/**
* Check if the content was changed
*
* This evaluation has to be made by classes using this
* particular class.
*
* \return true if changed, otherwise false
*/
bool changed() const { return _changed; }
/**
* Acknowledge the content has changed
*/
void acknowledge_change()
{
_changed = false;
_refresh_content();
}
};
/**
* File interface
*/
class Trace_fs::File : public Node
{
public:
File(char const *name)
{
Node::name(name);
}
virtual ~File() { }
/********************
** Node interface **
********************/
virtual size_t read(char *dst, size_t len, seek_off_t seek_offset) = 0;
virtual size_t write(char const *src, size_t len, seek_off_t seek_offset) = 0;
virtual Status status() const = 0;
/********************
** File interface **
********************/
virtual file_size_t length() const = 0;
virtual void truncate(file_size_t size) = 0;
};
/**
* Memory buffered file
*
* This file merely exists in memory and grows automatically.
*/
class Trace_fs::Buffered_file : public File
{
private:
typedef Chunk<4096> Chunk_level_3;
typedef Chunk_index<128, Chunk_level_3> Chunk_level_2;
typedef Chunk_index<64, Chunk_level_2> Chunk_level_1;
typedef Chunk_index<64, Chunk_level_1> Chunk_level_0;
Chunk_level_0 _chunk;
file_size_t _length;
public:
Buffered_file(Allocator &alloc, char const *name)
: File(name), _chunk(alloc, 0), _length(0) { }
virtual size_t read(char *dst, size_t len, seek_off_t seek_offset)
{
file_size_t const chunk_used_size = _chunk.used_size();
if (seek_offset >= _length)
return 0;
/*
* Constrain read transaction to available chunk data
*
* Note that 'chunk_used_size' may be lower than '_length'
* because 'Chunk' may have truncated tailing zeros.
*/
if (seek_offset + len >= _length)
len = _length - seek_offset;
file_size_t read_len = len;
if (seek_offset + read_len > chunk_used_size) {
if (chunk_used_size >= seek_offset)
read_len = chunk_used_size - seek_offset;
else
read_len = 0;
}
_chunk.read(dst, read_len, seek_offset);
/* add zero padding if needed */
if (read_len < len)
memset(dst + read_len, 0, len - read_len);
return len;
}
virtual size_t write(char const *src, size_t len, seek_off_t seek_offset)
{
if (seek_offset == (seek_off_t)(~0))
seek_offset = _chunk.used_size();
if (seek_offset + len >= Chunk_level_0::SIZE) {
len = (Chunk_level_0::SIZE-1) - seek_offset;
Genode::error(name(), ": size limit ", (long)Chunk_level_0::SIZE, " reached");
}
_chunk.write(src, len, (size_t)seek_offset);
/*
* Keep track of file length. We cannot use 'chunk.used_size()'
* as file length because trailing zeros may by represented
* by zero chunks, which do not contribute to 'used_size()'.
*/
_length = max(_length, seek_offset + len);
mark_as_updated();
return len;
}
virtual Status status() const
{
Status s;
s.inode = inode();
s.size = _length;
s.mode = File_system::Status::MODE_FILE;
return s;
}
virtual file_size_t length() const { return _length; }
void truncate(file_size_t size) override
{
if (size < _chunk.used_size())
_chunk.truncate(size);
_length = size;
mark_as_updated();
}
};
#endif /* _FILE_H_ */

View File

@ -1,283 +0,0 @@
/*
* \brief Facility for managing the trace subjects
* \author Josef Soentgen
* \date 2014-01-22
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SUBJECT_REGISTRY_H_
#define _SUBJECT_REGISTRY_H_
#include <base/allocator.h>
#include <base/lock.h>
#include <base/trace/types.h>
#include <directory.h>
#include <trace_files.h>
namespace Trace_fs {
typedef Genode::size_t size_t;
class Followed_subject;
class Followed_subject_registry;
}
class Trace_fs::Followed_subject : public Directory
{
public:
/**
* This class manages the access to the trace subject's trace buffer
*/
class Trace_buffer_manager
{
public:
class Already_managed { };
class Not_managed { };
struct Process_entry
{
virtual size_t operator()(Genode::Trace::Buffer::Entry&) = 0;
};
private:
Genode::Trace::Buffer *buffer;
Genode::Trace::Buffer::Entry current_entry;
public:
Trace_buffer_manager(Genode::Region_map &rm,
Genode::Dataspace_capability ds_cap)
:
buffer(rm.attach(ds_cap)),
current_entry(buffer->first())
{ }
size_t dump_entry(Process_entry &process)
{
size_t len = process(current_entry);
current_entry = buffer->next(current_entry);
return len;
}
bool last_entry() const
{
return current_entry.last();
}
void rewind() { current_entry = buffer->first(); }
};
private:
Genode::Allocator &_md_alloc;
Genode::Region_map &_rm;
int _handle;
Genode::Trace::Subject_id _id;
Genode::Trace::Policy_id _policy_id;
bool _was_traced;
Trace_buffer_manager *_buffer_manager;
public:
Active_file active_file;
Buffer_size_file buffer_size_file;
Cleanup_file cleanup_file;
Enable_file enable_file;
Events_file events_file;
Policy_file policy_file;
Followed_subject(Genode::Allocator &md_alloc, char const *name,
Genode::Region_map &rm,
Genode::Trace::Subject_id &id, int handle)
:
Directory(name),
_md_alloc(md_alloc),
_rm(rm),
_handle(handle),
_id(id),
_was_traced(false),
_buffer_manager(0),
active_file(_id),
buffer_size_file(),
cleanup_file(_id),
enable_file(_id),
events_file(_id, _md_alloc),
policy_file(_id, _md_alloc)
{
adopt_unsynchronized(&active_file);
adopt_unsynchronized(&cleanup_file);
adopt_unsynchronized(&enable_file);
adopt_unsynchronized(&events_file);
adopt_unsynchronized(&buffer_size_file);
adopt_unsynchronized(&policy_file);
}
~Followed_subject()
{
discard_unsynchronized(&active_file);
discard_unsynchronized(&cleanup_file);
discard_unsynchronized(&enable_file);
discard_unsynchronized(&events_file);
discard_unsynchronized(&buffer_size_file);
discard_unsynchronized(&policy_file);
}
bool marked_for_cleanup() const { return cleanup_file.cleanup(); }
bool was_traced() const { return _was_traced; }
Trace_buffer_manager* trace_buffer_manager() { return _buffer_manager; }
void manage_trace_buffer(Genode::Dataspace_capability ds_cap)
{
if (_buffer_manager != 0)
throw Trace_buffer_manager::Already_managed();
_buffer_manager = new (&_md_alloc) Trace_buffer_manager(_rm, ds_cap);
}
void unmanage_trace_buffer()
{
if (_buffer_manager == 0)
throw Trace_buffer_manager::Not_managed();
destroy(&_md_alloc, _buffer_manager);
_buffer_manager = 0;
}
const Genode::Trace::Subject_id id() const { return _id; }
const Genode::Trace::Policy_id policy_id() const { return _policy_id; }
void policy_id(Genode::Trace::Policy_id &id) { _policy_id.id = id.id; }
bool policy_valid() const { return (_policy_id.id != 0); }
void invalidate_policy() { _policy_id = Genode::Trace::Policy_id(); }
int handle() const { return _handle; }
};
/**
* This registry contains all current followed trace subjects
*/
class Trace_fs::Followed_subject_registry
{
public:
class Invalid_subject { };
class Out_of_subject_handles { };
private:
/* XXX abitrary limit - needs to be revisited when highly
* dynamic scenarios are executed */
enum { MAX_SUBJECTS = 1024U };
Followed_subject *_subjects[MAX_SUBJECTS];
Genode::Allocator &_md_alloc;
/**
* Find free subject handle
*
* \throw Out_of_subject_handles
*/
int _find_free_handle()
{
for (unsigned i = 0; i < MAX_SUBJECTS; i++)
if (!_subjects[i]) {
return i;
}
throw Out_of_subject_handles();
}
bool _in_range(int handle) const
{
return ((handle >= 0) && (handle < MAX_SUBJECTS));
}
public:
Followed_subject_registry(Genode::Allocator &md_alloc)
:
_md_alloc(md_alloc)
{
for (unsigned i = 0; i < MAX_SUBJECTS; i++)
_subjects[i] = 0;
}
/**
* Return maximal number of subject that can be stored in the registry
*
* \return maximal number of subjects
*/
unsigned max_subjects() const { return MAX_SUBJECTS; }
/**
* Allocate new subject
*
* \param name name of subject
* \param id subject id of tracre subject
*/
Followed_subject *alloc(char const *name, Genode::Trace::Subject_id &id,
Genode::Region_map &rm)
{
int handle = _find_free_handle();
_subjects[handle] = new (&_md_alloc) Followed_subject(_md_alloc, name, rm, id, handle);
return _subjects[handle];
}
/**
* Free subject
*
* \param subject pointer to subject
*/
void free(Followed_subject *subject)
{
int handle = subject->handle();
if (!_in_range(handle))
return;
if(!_subjects[handle])
return;
_subjects[handle] = 0;
destroy(&_md_alloc, subject);
}
/**
* Lookup subject by using the id
*
* \throw Invalid_subject();
*/
Followed_subject *lookup(Genode::Trace::Subject_id const &sid)
{
for (unsigned i = 0; i < MAX_SUBJECTS; i++)
if (_subjects[i]) {
if (_subjects[i]->id().id == sid.id)
return _subjects[i];
}
throw Invalid_subject();
}
};
#endif /* _SUBJECT_REGISTRY_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,89 +0,0 @@
/*
* \brief File-system node
* \author Norman Feske
* \date 2012-04-11
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _NODE_H_
#define _NODE_H_
/* Genode includes */
#include <file_system/node.h>
#include <util/list.h>
#include <base/lock.h>
#include <base/signal.h>
namespace Trace_fs {
using namespace File_system;
using namespace Genode;
class Node;
}
class Trace_fs::Node : public Node_base, public Weak_object<Node>,
public List<Node>::Element
{
public:
typedef char Name[128];
private:
Name _name;
unsigned long const _inode;
/**
* Generate unique inode number
*/
static unsigned long _unique_inode()
{
static unsigned long inode_count;
return ++inode_count;
}
public:
Node()
: _inode(_unique_inode())
{ _name[0] = 0; }
virtual ~Node() { lock_for_destruction(); }
unsigned long inode() const { return _inode; }
char const *name() const { return _name; }
/**
* Assign name
*/
void name(char const *name) { strncpy(_name, name, sizeof(_name)); }
virtual Status status() const = 0;
virtual size_t read(char *dst, size_t len, seek_off_t) = 0;
virtual size_t write(char const *src, size_t len, seek_off_t) = 0;
/*
* Directory functionality
*/
virtual Node *lookup(char const *path, bool return_parent = false)
{
Genode::error(__PRETTY_FUNCTION__, " called on a non-directory node");
return nullptr;
}
/*
* File functionality
*/
virtual void truncate(file_size_t size)
{
Genode::error(__PRETTY_FUNCTION__, " called on a non-file node");
}
};
#endif /* _NODE_H_ */

View File

@ -1,41 +0,0 @@
/*
* \brief Symlink file-system node
* \author Norman Feske
* \date 2012-04-11
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SYMLINK_H_
#define _SYMLINK_H_
/* local includes */
#include <file.h>
namespace Trace_fs {
class Symlink;
}
class Trace_fs::Symlink : public File
{
public:
Symlink(char const *name) : File(name) { }
size_t read(char *dst, size_t len, seek_off_t seek_offset) {
return 0; }
size_t write(char const *src, size_t len, seek_off_t seek_offset) {
return 0; }
file_size_t length() const { return 0; }
void truncate(file_size_t) { }
};
#endif /* _SYMLINK_H_ */

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