/* * \brief Core main program * \author Norman Feske * \date 2006-07-12 */ /* * Copyright (C) 2006-2013 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ /* Genode includes */ #include #include #include #include #include #include /* core includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Genode; /* support for cap session component */ long Cap_session_component::_unique_id_cnt; /* pool of provided core services */ static Service_registry local_services; /*************************************** ** Core environment/platform support ** ***************************************/ Core_env * Genode::core_env() { /* * Make sure to initialize the platform before constructing the core * environment. */ platform(); /* * By placing the environment as static object here, we ensure that its * constructor gets called when this function is used the first time. */ static Core_env _env; return &_env; } Env * Genode::env() { return core_env(); } Platform *Genode::platform_specific() { static Platform _platform; return &_platform; } Platform_generic *Genode::platform() { return platform_specific(); } /************************* ** Core parent support ** *************************/ Session_capability Core_parent::session(Parent::Service_name const &name, Parent::Session_args const &args, Affinity const &affinity) { Service *service = local_services.find(name.string()); if (service) return service->session(args.string(), affinity); PWRN("service_name=\"%s\" arg=\"%s\" not handled", name.string(), args.string()); return Session_capability(); } /**************** ** Core child ** ****************/ class Core_child : public Child_policy { private: /* * Entry point used for serving the parent interface */ Rpc_entrypoint _entrypoint; enum { STACK_SIZE = 8*1024 }; Service_registry &_local_services; Child _child; public: /** * Constructor */ Core_child(Dataspace_capability elf_ds, Cap_session *cap_session, Ram_session_capability ram, Cpu_session_capability cpu, Rm_session_capability rm, Service_registry &services) : _entrypoint(cap_session, STACK_SIZE, "init", false), _local_services(services), _child(elf_ds, ram, cpu, rm, &_entrypoint, this, *_local_services.find(Ram_session::service_name()), *_local_services.find(Cpu_session::service_name()), *_local_services.find(Rm_session::service_name())) { _entrypoint.activate(); } /**************************** ** Child-policy interface ** ****************************/ void filter_session_args(const char *, char *args, Genode::size_t args_len) { using namespace Genode; char label_buf[Parent::Session_args::MAX_SIZE]; Arg_string::find_arg(args, "label").string(label_buf, sizeof(label_buf), ""); char value_buf[Parent::Session_args::MAX_SIZE]; Genode::snprintf(value_buf, sizeof(value_buf), "\"%s%s%s\"", "init", Genode::strcmp(label_buf, "") == 0 ? "" : " -> ", label_buf); Arg_string::set_arg(args, args_len, "label", value_buf); } const char *name() const { return "init"; } Service *resolve_session_request(const char *service, const char *) { return _local_services.find(service); } }; /*************** ** Core main ** ***************/ int main() { PDBG("--- create local services ---"); /* * Initialize root interfaces for our services */ Rpc_entrypoint *e = core_env()->entrypoint(); /* * Allocate session meta data on distinct dataspaces to enable independent * destruction (to enable quota trading) of session component objects. */ static Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session()); static Cap_root cap_root (e, &sliced_heap); static Ram_root ram_root (e, e, platform()->ram_alloc(), &sliced_heap); static Rom_root rom_root (e, e, platform()->rom_fs(), &sliced_heap); static Rm_root rm_root (e, e, e, &sliced_heap, core_env()->cap_session(), platform()->vm_start(), platform()->vm_size()); static Cpu_root cpu_root (e, e, rm_root.pager_ep(), &sliced_heap); static Pd_root pd_root (e, e, &sliced_heap); static Log_root log_root (e, &sliced_heap); static Io_mem_root io_mem_root (e, e, platform()->io_mem_alloc(), platform()->ram_alloc(), &sliced_heap); static Irq_root irq_root (core_env()->cap_session(), platform()->irq_alloc(), &sliced_heap); static Signal_root signal_root (&sliced_heap, core_env()->cap_session()); /* * Play our role as parent of init and declare our services. */ static Local_service ls[] = { Local_service(Rom_session::service_name(), &rom_root), Local_service(Ram_session::service_name(), &ram_root), Local_service(Cap_session::service_name(), &cap_root), Local_service(Rm_session::service_name(), &rm_root), Local_service(Cpu_session::service_name(), &cpu_root), Local_service(Pd_session::service_name(), &pd_root), Local_service(Log_session::service_name(), &log_root), Local_service(Io_mem_session::service_name(), &io_mem_root), Local_service(Irq_session::service_name(), &irq_root), Local_service(Signal_session::service_name(), &signal_root) }; /* make our local services known to service pool */ for (unsigned i = 0; i < sizeof(ls) / sizeof(Local_service); i++) local_services.insert(&ls[i]); /* make platform-specific services known to service pool */ platform_add_local_services(e, &sliced_heap, &local_services); PDBG("--- start init ---"); /* obtain ROM session with init binary */ Rom_session_capability init_rom_session_cap; try { static Rom_connection rom("init"); init_rom_session_cap = rom.cap(); } catch (...) { PERR("ROM module \"init\" not present"); } /* create ram session for init and transfer some of our own quota */ Ram_session_capability init_ram_session_cap = static_cap_cast(ram_root.session("ram_quota=32K", Affinity())); Ram_session_client(init_ram_session_cap).ref_account(env()->ram_session_cap()); Cpu_connection init_cpu("init"); Rm_connection init_rm; /* transfer all left memory to init, but leave some memory left for core */ /* NOTE: exception objects thrown in core components are currently allocated on core's heap and not accounted by the component's meta data allocator */ Genode::size_t init_quota = platform()->ram_alloc()->avail() - 172*1024; env()->ram_session()->transfer_quota(init_ram_session_cap, init_quota); PDBG("transferred %zd MB to init", init_quota / (1024*1024)); Core_child *init = new (env()->heap()) Core_child(Rom_session_client(init_rom_session_cap).dataspace(), core_env()->cap_session(), init_ram_session_cap, init_cpu.cap(), init_rm.cap(), local_services); PDBG("--- init created, waiting for exit condition ---"); platform()->wait_for_exit(); PDBG("--- destroying init ---"); destroy(env()->heap(), init); rom_root.close(init_rom_session_cap); ram_root.close(init_ram_session_cap); PDBG("--- core main says good bye ---"); return 0; }