21#include "pedigree/kernel/BootstrapInfo.h"
22#include "pedigree/kernel/LockGuard.h"
23#include "pedigree/kernel/Version.h"
24#include "pedigree/kernel/machine/Device.h"
25#include "pedigree/kernel/process/Scheduler.h"
26#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
27#include "pedigree/kernel/time/Time.h"
28#include "pedigree/kernel/utilities/StaticString.h"
30#include "PosixProcess.h"
31#include "file-syscalls.h"
32#include "modules/system/users/Group.h"
33#include "modules/system/users/User.h"
36Mutex procRegistryLock;
37ProcFs* procRegistry =
nullptr;
41extern size_t g_FreePages;
42extern size_t g_AllocedPages;
44MeminfoFile::MeminfoFile(
size_t inode,
Filesystem* pParentFS,
File* pParent)
45 :
File(
String(
"meminfo"), 0, 0, 0, inode, pParentFS, 0, pParent), m_Contents(), m_Lock() {
46 setPermissionsOnly(FILE_UR | FILE_GR | FILE_OR);
53MeminfoFile::~MeminfoFile() =
default;
55size_t MeminfoFile::getSize() {
58 return m_Contents.length();
61void MeminfoFile::updateContents() {
63 const uint64_t totalPages = memory.available ? memory.totalPages : g_FreePages + g_AllocedPages;
64 const uint64_t freePages = memory.available ? memory.freePages : g_FreePages;
71 "MemAvailable: %lu kB\n"
77 totalKb, freeKb, freeKb);
79 m_Contents = contents;
87 if (location >= m_Contents.length()) {
89 }
else if (size > m_Contents.length() - location) {
90 size = m_Contents.length() - location;
93 char* destination =
reinterpret_cast<char*
>(buffer);
94 const char* source =
static_cast<const char*
>(m_Contents);
96 MemoryCopy(destination, source + location, size);
106PciDevicesFile::PciDevicesFile(
size_t inode,
Filesystem* pParentFS,
File* pParent)
107 :
File(
String(
"devices"), 0, 0, 0, inode, pParentFS, 0, pParent), m_Contents() {
115PciDevicesFile::~PciDevicesFile() {}
117size_t PciDevicesFile::getSize() {
118 return m_Contents.length();
125 if (location >= m_Contents.length()) {
127 }
else if ((location + size) > m_Contents.length()) {
128 size = m_Contents.length() - location;
131 char* destination =
reinterpret_cast<char*
>(buffer);
132 const char* source =
static_cast<const char*
>(m_Contents);
134 StringCopy(destination, source);
149 initial.Format(
"%02x%02x\t%04x%04x\t%x", p->getPciBusPosition(),
150 (p->getPciDevicePosition() << 4) | p->getPciFunctionNumber(),
151 p->getPciVendorId(), p->getPciDeviceId(), p->getInterruptNumber());
155 for (
size_t i = 0; i < 7; ++i) {
159 if (i < p->addresses().count()) {
160 size_t length = p->addresses()[i]->m_Size;
162 uintptr_t address = p->addresses()[i]->m_Address;
164 if (p->addresses()[i]->m_IsIoSpace) {
169 thisResStart.Format(
"\t%16lx", address | flags);
170 thisResLength.Format(
"\t%16lx", length ? length + 1 : 0);
172 thisResStart.Format(
"\t%16lx", 0);
173 thisResLength.Format(
"\t%16lx", 0);
176 resStart += thisResStart;
177 resLength += thisResLength;
180 m_Contents += initial;
181 m_Contents += resStart;
182 m_Contents += resLength;
189 auto callback = pedigree_std::make_callable(printer);
193MountFile::MountFile(
size_t inode,
Filesystem* pParentFS,
File* pParent)
194 :
File(
String(
"mounts"), 0, 0, 0, inode, pParentFS, 0, pParent) {
200MountFile::~MountFile() =
default;
205 generate_mtab(mounts);
207 if (location >= mounts.length()) {
212 if ((location + size) >= mounts.length()) {
213 size = mounts.length() - location;
216 char* destination =
reinterpret_cast<char*
>(buffer);
217 StringCopyN(destination,
static_cast<const char*
>(mounts) + location, size);
227size_t MountFile::getSize() {
229 generate_mtab(mounts);
230 return mounts.length();
233UptimeFile::UptimeFile(
size_t inode,
Filesystem* pParentFS,
File* pParent)
234 :
File(
String(
"uptime"), 0, 0, 0, inode, pParentFS, 0, pParent) {
240UptimeFile::~UptimeFile() =
default;
244 String f = generateString();
246 if (location >= f.length()) {
251 if ((location + size) >= f.length()) {
252 size = f.length() - location;
255 char* destination =
reinterpret_cast<char*
>(buffer);
256 StringCopyN(destination,
static_cast<const char*
>(f) + location, size);
266size_t UptimeFile::getSize() {
267 String f = generateString();
271String UptimeFile::generateString() {
272 const uint64_t uptime = Time::getTicks();
276 f.Format(
"%lu.%02lu %lu.%02lu\n", uptime / Time::Multiplier::Second,
277 (uptime % Time::Multiplier::Second) / (Time::Multiplier::Second / 100),
278 idle / Time::Multiplier::Second,
279 (idle % Time::Multiplier::Second) / (Time::Multiplier::Second / 100));
284ConstantFile::ConstantFile(
String name,
const char* value,
size_t size,
size_t inode,
286 :
File(name, 0, 0, 0, inode, pParentFS, 0, pParent), m_Contents() {
291 m_Contents =
new char[size];
293 MemoryCopy(m_Contents, value, size);
296ConstantFile::~ConstantFile() {
302 if (location >= m_Size) {
304 }
else if ((location + size) > m_Size) {
305 size = m_Size - location;
308 char* destination =
reinterpret_cast<char*
>(buffer);
309 const char* source = m_Contents + location;
311 MemoryCopy(destination, source, size);
321size_t ConstantFile::getSize() {
325ProcFsDirectory::~ProcFsDirectory() =
default;
330 ProcFs** link = &procRegistry;
331 while (*link && *link !=
this) {
332 link = &(*link)->m_RegistryNext;
335 *link = m_RegistryNext;
356 m_pRoot->setPermissions(FILE_UR | FILE_UW | FILE_UX | FILE_GR | FILE_GW | FILE_GX | FILE_OR |
362 dot->setPermissions(m_pRoot->getPermissions());
363 m_pRoot->addEntry(dot->
getName(), dot);
366 m_pRoot->addEntry(meminfo->
getName(), meminfo);
370 m_pRoot->addEntry(mounts->
getName(), mounts);
372 initialiseResolverFile();
373 initialiseNetworkFile();
377 constexpr uint32_t directoryMode = FILE_UR | FILE_UX | FILE_GR | FILE_GX | FILE_OR | FILE_OX;
378 sys->setPermissions(directoryMode);
379 kernel->setPermissions(directoryMode);
380 m_pRoot->addEntry(sys->getName(), sys);
381 sys->addEntry(kernel->getName(), kernel);
382 const char* overflowNames[] = {
"overflowuid",
"overflowgid"};
383 for (
const char* name : overflowNames) {
384 auto* value =
new ConstantFile(
String(name),
"65534\n", 6, getNextInode(),
this, kernel);
385 value->setPermissions(FILE_UR | FILE_GR | FILE_OR);
386 kernel->addEntry(value->getName(), value);
390 m_pRoot->addEntry(uptime->
getName(), uptime);
392 if (!procfsAddSystemStatusFiles(*
this, *m_pRoot))
395 static String fs(
"\text2\nnodev\tproc\nnodev\tsysfs\nnodev\ttmpfs\n");
397 getNextInode(),
this, m_pRoot);
398 m_pRoot->addEntry(pFilesystems->
getName(), pFilesystems);
401 static String cmdline(
"noswap quiet boot=live\n", 25);
402 NOTICE(
"cmdline is '" << cmdline <<
"'");
404 getNextInode(),
this, m_pRoot);
405 m_pRoot->addEntry(pCmdline->
getName(), pCmdline);
409 version.Format(
"Pedigree version %s (%s@%s) %s", g_pBuildRevision, g_pBuildUser, g_pBuildMachine,
412 getNextInode(),
this, m_pRoot);
413 m_pRoot->addEntry(pVersion->
getName(), pVersion);
420 pBusDir->setPermissions(FILE_UR | FILE_UX | FILE_GR | FILE_GX | FILE_OR | FILE_OX);
421 pPciDir->setPermissions(FILE_UR | FILE_UX | FILE_GR | FILE_GX | FILE_OR | FILE_OX);
423 m_pRoot->addEntry(pBusDir->
getName(), pBusDir);
424 pBusDir->addEntry(pPciDir->
getName(), pPciDir);
429 bus.Format(
"%02x", p->getPciBusPosition());
435 pPciDir->addEntry(dir->
getName(), dir);
443 fn.Format(
"%02x.%01x", p->getPciDevicePosition(), p->getPciFunctionNumber());
452 getNextInode(),
this, dir);
453 dir->addEntry(cf->
getName(), cf);
457 initial.Format(
"%02x%02x\t%04x%04x\t%x", p->getPciBusPosition(),
458 (p->getPciDevicePosition() << 4) | p->getPciFunctionNumber(),
459 p->getPciVendorId(), p->getPciDeviceId(), p->getInterruptNumber());
463 for (
size_t i = 0; i < 7; ++i) {
467 if (i < p->addresses().count()) {
468 size_t length = p->addresses()[i]->m_Size;
470 uintptr_t address = p->addresses()[i]->m_Address;
472 if (p->addresses()[i]->m_IsIoSpace) {
477 thisResStart.Format(
"\t%16lx", address | flags);
478 thisResLength.Format(
"\t%16lx", length ? length + 1 : 0);
480 thisResStart.Format(
"\t%16lx", 0);
481 thisResLength.Format(
"\t%16lx", 0);
484 resStart += thisResStart;
485 resLength += thisResLength;
488 m_PciDevices += initial;
489 m_PciDevices += resStart;
490 m_PciDevices += resLength;
491 m_PciDevices +=
"\t";
492 m_PciDevices +=
"\n";
497 auto callback = pedigree_std::make_callable(printer);
501 String(
"devices"), m_PciDevices.cstr(), m_PciDevices.length(), getNextInode(),
this, pPciDir);
502 pPciDir->addEntry(pPciDevices->
getName(), pPciDevices);
504 if (!initialiseNamespaceLinks()) {
509 m_RegistryNext = procRegistry;
516 after = process->
getId();
517 if (process->getType() == Process::Posix) {
524size_t ProcFs::getNextInode() {
525 return (m_NextInode += 1) - 1;
528void ProcFs::revertInode() {
545 auto procDir = createProcessDirectory(proc);
547 WARNING(
"ProcFs: could not prepare process directory for " <<
Dec << pid);
550 procDir->setPermissions(FILE_UR | FILE_UX | FILE_GR | FILE_GX | FILE_OR | FILE_OX);
561 m_pRoot->addEntry(procDir->getName(), procDir);
580 for (
auto* filesystem = procRegistry; filesystem; filesystem = filesystem->m_RegistryNext) {
581 filesystem->addProcess(process);
587 for (
auto* filesystem = procRegistry; filesystem; filesystem = filesystem->m_RegistryNext) {
588 filesystem->removeProcess(process);
virtual uint64_t writeBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
virtual uint64_t readBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
static void foreach(Callback callback, Device *root=0)
static Directory * fromFile(File *pF)
void remove(const HashedStringView &s)
MUST_USE_RESULT LookupStatus lookupChild(const HashedStringView &s, ChildLease &child) const
void setGidOnly(size_t gid)
void setPermissionsOnly(uint32_t perms)
void setUidOnly(size_t uid)
virtual uint64_t readBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
virtual uint64_t writeBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
virtual uint64_t writeBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
virtual uint64_t readBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
virtual uint64_t readBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
virtual uint64_t writeBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
static PhysicalMemoryManager & instance()
static constexpr size_t getPageSize() PURE
void addProcess(PosixProcess *proc)
virtual bool initialise(Disk *pDisk)
size_t getUserspaceId() const
static Scheduler & instance()
virtual uint64_t writeBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
virtual uint64_t readBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
File * find(const String &path, File *pStartNode=0)