procfs.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2014-2018 K. Lange
  5. */
  6. #include <kernel/system.h>
  7. #include <kernel/logging.h>
  8. #include <kernel/fs.h>
  9. #include <kernel/version.h>
  10. #include <kernel/process.h>
  11. #include <kernel/printf.h>
  12. #include <kernel/module.h>
  13. #include <kernel/multiboot.h>
  14. #include <kernel/pci.h>
  15. #include <kernel/mod/procfs.h>
  16. #define PROCFS_STANDARD_ENTRIES (sizeof(std_entries) / sizeof(struct procfs_entry))
  17. #define PROCFS_PROCDIR_ENTRIES (sizeof(procdir_entries) / sizeof(struct procfs_entry))
  18. static fs_node_t * procfs_generic_create(char * name, read_type_t read_func) {
  19. fs_node_t * fnode = malloc(sizeof(fs_node_t));
  20. memset(fnode, 0x00, sizeof(fs_node_t));
  21. fnode->inode = 0;
  22. strcpy(fnode->name, name);
  23. fnode->uid = 0;
  24. fnode->gid = 0;
  25. fnode->mask = 0444;
  26. fnode->flags = FS_FILE;
  27. fnode->read = read_func;
  28. fnode->write = NULL;
  29. fnode->open = NULL;
  30. fnode->close = NULL;
  31. fnode->readdir = NULL;
  32. fnode->finddir = NULL;
  33. fnode->ctime = now();
  34. fnode->mtime = now();
  35. fnode->atime = now();
  36. return fnode;
  37. }
  38. static uint32_t proc_cmdline_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  39. char buf[1024];
  40. process_t * proc = process_from_pid(node->inode);
  41. if (!proc) {
  42. /* wat */
  43. return 0;
  44. }
  45. if (!proc->cmdline) {
  46. sprintf(buf, "%s", proc->name);
  47. size_t _bsize = strlen(buf);
  48. if (offset > _bsize) return 0;
  49. if (size > _bsize - offset) size = _bsize - offset;
  50. memcpy(buffer, buf + offset, size);
  51. return size;
  52. }
  53. buf[0] = '\0';
  54. char * _buf = buf;
  55. char ** args = proc->cmdline;
  56. while (*args) {
  57. strcpy(_buf, *args);
  58. _buf += strlen(_buf);
  59. if (*(args+1)) {
  60. strcpy(_buf, "\036");
  61. _buf += strlen(_buf);
  62. }
  63. args++;
  64. }
  65. size_t _bsize = strlen(buf);
  66. if (offset > _bsize) return 0;
  67. if (size > _bsize - offset) size = _bsize - offset;
  68. memcpy(buffer, buf + offset, size);
  69. return size;
  70. }
  71. static size_t calculate_memory_usage(page_directory_t * src) {
  72. size_t pages = 0;
  73. for (uint32_t i = 0; i < 1024; ++i) {
  74. if (!src->tables[i] || (uintptr_t)src->tables[i] == (uintptr_t)0xFFFFFFFF) {
  75. continue;
  76. }
  77. if (kernel_directory->tables[i] == src->tables[i]) {
  78. continue;
  79. }
  80. /* For each table */
  81. if (i * 0x1000 * 1024 < SHM_START) {
  82. /* Ignore shared memory for now */
  83. for (int j = 0; j < 1024; ++j) {
  84. /* For each frame in the table... */
  85. if (!src->tables[i]->pages[j].frame) {
  86. continue;
  87. }
  88. pages++;
  89. }
  90. }
  91. }
  92. return pages;
  93. }
  94. static size_t calculate_shm_resident(page_directory_t * src) {
  95. size_t pages = 0;
  96. for (uint32_t i = 0; i < 1024; ++i) {
  97. if (!src->tables[i] || (uintptr_t)src->tables[i] == (uintptr_t)0xFFFFFFFF) {
  98. continue;
  99. }
  100. if (kernel_directory->tables[i] == src->tables[i]) {
  101. continue;
  102. }
  103. if (i * 0x1000 * 1024 < SHM_START) {
  104. continue;
  105. }
  106. for (int j = 0; j < 1024; ++j) {
  107. /* For each frame in the table... */
  108. if (!src->tables[i]->pages[j].frame) {
  109. continue;
  110. }
  111. pages++;
  112. }
  113. }
  114. return pages;
  115. }
  116. static uint32_t proc_status_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  117. char buf[2048];
  118. process_t * proc = process_from_pid(node->inode);
  119. process_t * parent = process_get_parent(proc);
  120. if (!proc) {
  121. /* wat */
  122. return 0;
  123. }
  124. char state = proc->finished ? 'Z' : (process_is_ready(proc) ? 'R' : 'S');
  125. char * name = proc->name + strlen(proc->name) - 1;
  126. while (1) {
  127. if (*name == '/') {
  128. name++;
  129. break;
  130. }
  131. if (name == proc->name) break;
  132. name--;
  133. }
  134. /* Calculate process memory usage */
  135. int mem_usage = calculate_memory_usage(proc->thread.page_directory) * 4;
  136. int shm_usage = calculate_shm_resident(proc->thread.page_directory) * 4;
  137. int mem_permille = 1000 * (mem_usage + shm_usage) / memory_total();
  138. sprintf(buf,
  139. "Name:\t%s\n" /* name */
  140. "State:\t%c\n" /* yeah, do this at some point */
  141. "Tgid:\t%d\n" /* group ? group : pid */
  142. "Pid:\t%d\n" /* pid */
  143. "PPid:\t%d\n" /* parent pid */
  144. "Uid:\t%d\n"
  145. "Ueip:\t0x%x\n"
  146. "SCid:\t%d\n"
  147. "SC0:\t0x%x\n"
  148. "SC1:\t0x%x\n"
  149. "SC2:\t0x%x\n"
  150. "SC3:\t0x%x\n"
  151. "SC4:\t0x%x\n"
  152. "UserStack:\t0x%x\n"
  153. "Path:\t%s\n"
  154. "VmSize:\t %d kB\n"
  155. "RssShmem:\t %d kB\n"
  156. "MemPermille:\t %d\n"
  157. ,
  158. name,
  159. state,
  160. proc->group ? proc->group : proc->id,
  161. proc->id,
  162. parent ? parent->id : 0,
  163. proc->user,
  164. proc->syscall_registers ? proc->syscall_registers->eip : 0,
  165. proc->syscall_registers ? proc->syscall_registers->eax : 0,
  166. proc->syscall_registers ? proc->syscall_registers->ebx : 0,
  167. proc->syscall_registers ? proc->syscall_registers->ecx : 0,
  168. proc->syscall_registers ? proc->syscall_registers->edx : 0,
  169. proc->syscall_registers ? proc->syscall_registers->esi : 0,
  170. proc->syscall_registers ? proc->syscall_registers->edi : 0,
  171. proc->syscall_registers ? proc->syscall_registers->useresp : 0,
  172. proc->cmdline ? proc->cmdline[0] : "(none)",
  173. mem_usage, shm_usage, mem_permille
  174. );
  175. size_t _bsize = strlen(buf);
  176. if (offset > _bsize) return 0;
  177. if (size > _bsize - offset) size = _bsize - offset;
  178. memcpy(buffer, buf + offset, size);
  179. return size;
  180. }
  181. static struct procfs_entry procdir_entries[] = {
  182. {1, "cmdline", proc_cmdline_func},
  183. {2, "status", proc_status_func},
  184. };
  185. static struct dirent * readdir_procfs_procdir(fs_node_t *node, uint32_t index) {
  186. if (index == 0) {
  187. struct dirent * out = malloc(sizeof(struct dirent));
  188. memset(out, 0x00, sizeof(struct dirent));
  189. out->ino = 0;
  190. strcpy(out->name, ".");
  191. return out;
  192. }
  193. if (index == 1) {
  194. struct dirent * out = malloc(sizeof(struct dirent));
  195. memset(out, 0x00, sizeof(struct dirent));
  196. out->ino = 0;
  197. strcpy(out->name, "..");
  198. return out;
  199. }
  200. index -= 2;
  201. if (index < PROCFS_PROCDIR_ENTRIES) {
  202. struct dirent * out = malloc(sizeof(struct dirent));
  203. memset(out, 0x00, sizeof(struct dirent));
  204. out->ino = procdir_entries[index].id;
  205. strcpy(out->name, procdir_entries[index].name);
  206. return out;
  207. }
  208. return NULL;
  209. }
  210. static fs_node_t * finddir_procfs_procdir(fs_node_t * node, char * name) {
  211. if (!name) return NULL;
  212. for (unsigned int i = 0; i < PROCFS_PROCDIR_ENTRIES; ++i) {
  213. if (!strcmp(name, procdir_entries[i].name)) {
  214. fs_node_t * out = procfs_generic_create(procdir_entries[i].name, procdir_entries[i].func);
  215. out->inode = node->inode;
  216. return out;
  217. }
  218. }
  219. return NULL;
  220. }
  221. static fs_node_t * procfs_procdir_create(process_t * process) {
  222. pid_t pid = process->id;
  223. fs_node_t * fnode = malloc(sizeof(fs_node_t));
  224. memset(fnode, 0x00, sizeof(fs_node_t));
  225. fnode->inode = pid;
  226. sprintf(fnode->name, "%d", pid);
  227. fnode->uid = 0;
  228. fnode->gid = 0;
  229. fnode->mask = 0555;
  230. fnode->flags = FS_DIRECTORY;
  231. fnode->read = NULL;
  232. fnode->write = NULL;
  233. fnode->open = NULL;
  234. fnode->close = NULL;
  235. fnode->readdir = readdir_procfs_procdir;
  236. fnode->finddir = finddir_procfs_procdir;
  237. fnode->nlink = 1;
  238. fnode->ctime = process->start.tv_sec;
  239. fnode->mtime = process->start.tv_sec;
  240. fnode->atime = process->start.tv_sec;
  241. return fnode;
  242. }
  243. #define cpuid(in,a,b,c,d) do { asm volatile ("cpuid" : "=a"(a),"=b"(b),"=c"(c),"=d"(d) : "a"(in)); } while(0)
  244. static uint32_t cpuinfo_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  245. char buf[1024];
  246. unsigned long a, b, unused;;
  247. cpuid(0,unused,b,unused,unused);
  248. char * _manu = "Unknown";
  249. int _model = 0, _family = 0;
  250. if (b == 0x756e6547) {
  251. cpuid(1, a, b, unused, unused);
  252. _manu = "Intel";
  253. _model = (a >> 4) & 0x0F;
  254. _family = (a >> 8) & 0x0F;
  255. } else if (b == 0x68747541) {
  256. cpuid(1, a, unused, unused, unused);
  257. _manu = "AMD";
  258. _model = (a >> 4) & 0x0F;
  259. _family = (a >> 8) & 0x0F;
  260. }
  261. sprintf(buf,
  262. "Manufacturer: %s\n"
  263. "Family: %d\n"
  264. "Model: %d\n"
  265. , _manu, _family, _model);
  266. size_t _bsize = strlen(buf);
  267. if (offset > _bsize) return 0;
  268. if (size > _bsize - offset) size = _bsize - offset;
  269. memcpy(buffer, buf + offset, size);
  270. return size;
  271. }
  272. extern uintptr_t heap_end;
  273. extern uintptr_t kernel_heap_alloc_point;
  274. static uint32_t meminfo_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  275. char buf[1024];
  276. unsigned int total = memory_total();
  277. unsigned int free = total - memory_use();
  278. unsigned int kheap = (heap_end - kernel_heap_alloc_point) / 1024;
  279. sprintf(buf,
  280. "MemTotal: %d kB\n"
  281. "MemFree: %d kB\n"
  282. "KHeapUse: %d kB\n"
  283. , total, free, kheap);
  284. size_t _bsize = strlen(buf);
  285. if (offset > _bsize) return 0;
  286. if (size > _bsize - offset) size = _bsize - offset;
  287. memcpy(buffer, buf + offset, size);
  288. return size;
  289. }
  290. static uint32_t pat_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  291. char buf[1024];
  292. uint64_t pat_values;
  293. asm volatile ( "rdmsr" : "=A" (pat_values) : "c" (0x277) );
  294. char * pat_names[] = {
  295. "uncacheable (UC)",
  296. "write combining (WC)",
  297. "Reserved",
  298. "Reserved",
  299. "write through (WT)",
  300. "write protected (WP)",
  301. "write back (WB)",
  302. "uncached (UC-)"
  303. };
  304. int pa_0 = (pat_values >> 0) & 0x7;
  305. int pa_1 = (pat_values >> 8) & 0x7;
  306. int pa_2 = (pat_values >> 16) & 0x7;
  307. int pa_3 = (pat_values >> 24) & 0x7;
  308. int pa_4 = (pat_values >> 32) & 0x7;
  309. int pa_5 = (pat_values >> 40) & 0x7;
  310. int pa_6 = (pat_values >> 48) & 0x7;
  311. int pa_7 = (pat_values >> 56) & 0x7;
  312. sprintf(buf,
  313. "PA0: %d %s\n"
  314. "PA1: %d %s\n"
  315. "PA2: %d %s\n"
  316. "PA3: %d %s\n"
  317. "PA4: %d %s\n"
  318. "PA5: %d %s\n"
  319. "PA6: %d %s\n"
  320. "PA7: %d %s\n",
  321. pa_0, pat_names[pa_0],
  322. pa_1, pat_names[pa_1],
  323. pa_2, pat_names[pa_2],
  324. pa_3, pat_names[pa_3],
  325. pa_4, pat_names[pa_4],
  326. pa_5, pat_names[pa_5],
  327. pa_6, pat_names[pa_6],
  328. pa_7, pat_names[pa_7]
  329. );
  330. size_t _bsize = strlen(buf);
  331. if (offset > _bsize) return 0;
  332. if (size > _bsize - offset) size = _bsize - offset;
  333. memcpy(buffer, buf + offset, size);
  334. return size;
  335. }
  336. static uint32_t uptime_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  337. char buf[1024];
  338. sprintf(buf, "%d.%3d\n", timer_ticks, timer_subticks);
  339. size_t _bsize = strlen(buf);
  340. if (offset > _bsize) return 0;
  341. if (size > _bsize - offset) size = _bsize - offset;
  342. memcpy(buffer, buf + offset, size);
  343. return size;
  344. }
  345. static uint32_t cmdline_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  346. char buf[1024];
  347. extern char * cmdline;
  348. sprintf(buf, "%s\n", cmdline ? cmdline : "");
  349. size_t _bsize = strlen(buf);
  350. if (offset > _bsize) return 0;
  351. if (size > _bsize - offset) size = _bsize - offset;
  352. memcpy(buffer, buf + offset, size);
  353. return size;
  354. }
  355. static uint32_t version_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  356. char buf[1024];
  357. char version_number[512];
  358. sprintf(version_number, __kernel_version_format,
  359. __kernel_version_major,
  360. __kernel_version_minor,
  361. __kernel_version_lower,
  362. __kernel_version_suffix);
  363. sprintf(buf, "%s %s %s %s %s %s\n",
  364. __kernel_name,
  365. version_number,
  366. __kernel_version_codename,
  367. __kernel_build_date,
  368. __kernel_build_time,
  369. __kernel_arch);
  370. size_t _bsize = strlen(buf);
  371. if (offset > _bsize) return 0;
  372. if (size > _bsize - offset) size = _bsize - offset;
  373. memcpy(buffer, buf + offset, size);
  374. return size;
  375. }
  376. static uint32_t compiler_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  377. char buf[1024];
  378. sprintf(buf, "%s\n", __kernel_compiler_version);
  379. size_t _bsize = strlen(buf);
  380. if (offset > _bsize) return 0;
  381. if (size > _bsize - offset) size = _bsize - offset;
  382. memcpy(buffer, buf + offset, size);
  383. return size;
  384. }
  385. extern tree_t * fs_tree; /* kernel/fs/vfs.c */
  386. static void mount_recurse(char * buf, tree_node_t * node, size_t height) {
  387. /* End recursion on a blank entry */
  388. if (!node) return;
  389. char * tmp = malloc(512);
  390. memset(tmp, 0, 512);
  391. char * c = tmp;
  392. /* Indent output */
  393. for (uint32_t i = 0; i < height; ++i) {
  394. c += sprintf(c, " ");
  395. }
  396. /* Get the current process */
  397. struct vfs_entry * fnode = (struct vfs_entry *)node->value;
  398. /* Print the process name */
  399. if (fnode->file) {
  400. c += sprintf(c, "%s → %s 0x%x (%s, %s)", fnode->name, fnode->device, fnode->file, fnode->fs_type, fnode->file->name);
  401. } else {
  402. c += sprintf(c, "%s → (empty)", fnode->name);
  403. }
  404. /* Linefeed */
  405. sprintf(buf+strlen(buf),"%s\n",tmp);
  406. free(tmp);
  407. foreach(child, node->children) {
  408. /* Recursively print the children */
  409. mount_recurse(buf+strlen(buf),child->value, height + 1);
  410. }
  411. }
  412. static uint32_t mounts_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  413. char * buf = malloc(4096);
  414. buf[0] = '\0';
  415. mount_recurse(buf, fs_tree->root, 0);
  416. size_t _bsize = strlen(buf);
  417. if (offset > _bsize) {
  418. free(buf);
  419. return 0;
  420. }
  421. if (size > _bsize - offset) size = _bsize - offset;
  422. memcpy(buffer, buf + offset, size);
  423. free(buf);
  424. return size;
  425. }
  426. static uint32_t modules_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  427. list_t * hash_keys = hashmap_keys(modules_get_list());
  428. char * buf = malloc(hash_keys->length * 512);
  429. unsigned int soffset = 0;
  430. foreach(_key, hash_keys) {
  431. char * key = (char *)_key->value;
  432. module_data_t * mod_info = hashmap_get(modules_get_list(), key);
  433. soffset += sprintf(&buf[soffset], "0x%x {.init=0x%x, .fini=0x%x} %s",
  434. mod_info->bin_data,
  435. mod_info->mod_info->initialize,
  436. mod_info->mod_info->finalize,
  437. mod_info->mod_info->name);
  438. if (mod_info->deps) {
  439. unsigned int i = 0;
  440. soffset += sprintf(&buf[soffset], " Deps: ");
  441. while (i < mod_info->deps_length) {
  442. /* Skip padding bytes */
  443. if (strlen(&mod_info->deps[i])) {
  444. soffset += sprintf(&buf[soffset], "%s ", &mod_info->deps[i]);
  445. }
  446. i += strlen(&mod_info->deps[i]) + 1;
  447. }
  448. }
  449. soffset += sprintf(&buf[soffset], "\n");
  450. }
  451. free(hash_keys);
  452. size_t _bsize = strlen(buf);
  453. if (offset > _bsize) {
  454. free(buf);
  455. return 0;
  456. }
  457. if (size > _bsize - offset) size = _bsize - offset;
  458. memcpy(buffer, buf + offset, size);
  459. free(buf);
  460. return size;
  461. }
  462. extern hashmap_t * fs_types; /* from kernel/fs/vfs.c */
  463. static uint32_t filesystems_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  464. list_t * hash_keys = hashmap_keys(fs_types);
  465. char * buf = malloc(hash_keys->length * 512);
  466. unsigned int soffset = 0;
  467. foreach(_key, hash_keys) {
  468. char * key = (char *)_key->value;
  469. soffset += sprintf(&buf[soffset], "%s\n", key);
  470. }
  471. free(hash_keys);
  472. size_t _bsize = strlen(buf);
  473. if (offset > _bsize) {
  474. free(buf);
  475. return 0;
  476. }
  477. if (size > _bsize - offset) size = _bsize - offset;
  478. memcpy(buffer, buf + offset, size);
  479. free(buf);
  480. return size;
  481. }
  482. static uint32_t loader_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  483. char * buf = malloc(512);
  484. if (mboot_ptr->flags & MULTIBOOT_FLAG_LOADER) {
  485. sprintf(buf, "%s\n", mboot_ptr->boot_loader_name);
  486. } else {
  487. buf[0] = '\n';
  488. buf[1] = '\0';
  489. }
  490. size_t _bsize = strlen(buf);
  491. if (offset > _bsize) {
  492. free(buf);
  493. return 0;
  494. }
  495. if (size > _bsize - offset) size = _bsize - offset;
  496. memcpy(buffer, buf + offset, size);
  497. free(buf);
  498. return size;
  499. }
  500. extern char * get_irq_handler(int irq, int chain);
  501. static uint32_t irq_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  502. char * buf = malloc(4096);
  503. unsigned int soffset = 0;
  504. for (int i = 0; i < 16; ++i) {
  505. soffset += sprintf(&buf[soffset], "irq %d: ", i);
  506. for (int j = 0; j < 4; ++j) {
  507. char * t = get_irq_handler(i, j);
  508. if (!t) break;
  509. soffset += sprintf(&buf[soffset], "%s%s", j ? "," : "", t);
  510. }
  511. soffset += sprintf(&buf[soffset], "\n");
  512. }
  513. size_t _bsize = strlen(buf);
  514. if (offset > _bsize) {
  515. free(buf);
  516. return 0;
  517. }
  518. if (size > _bsize - offset) size = _bsize - offset;
  519. memcpy(buffer, buf + offset, size);
  520. free(buf);
  521. return size;
  522. }
  523. /**
  524. * Basically the same as the kdebug `pci` command.
  525. */
  526. struct _pci_buf {
  527. size_t offset;
  528. char *buffer;
  529. };
  530. static void scan_hit_list(uint32_t device, uint16_t vendorid, uint16_t deviceid, void * extra) {
  531. struct _pci_buf * b = extra;
  532. b->offset += sprintf(b->buffer + b->offset, "%2x:%2x.%d (%4x, %4x:%4x) %s %s\n",
  533. (int)pci_extract_bus(device),
  534. (int)pci_extract_slot(device),
  535. (int)pci_extract_func(device),
  536. (int)pci_find_type(device),
  537. vendorid,
  538. deviceid,
  539. pci_vendor_lookup(vendorid),
  540. pci_device_lookup(vendorid,deviceid));
  541. b->offset += sprintf(b->buffer + b->offset, " BAR0: 0x%8x", pci_read_field(device, PCI_BAR0, 4));
  542. b->offset += sprintf(b->buffer + b->offset, " BAR1: 0x%8x", pci_read_field(device, PCI_BAR1, 4));
  543. b->offset += sprintf(b->buffer + b->offset, " BAR2: 0x%8x", pci_read_field(device, PCI_BAR2, 4));
  544. b->offset += sprintf(b->buffer + b->offset, " BAR3: 0x%8x", pci_read_field(device, PCI_BAR3, 4));
  545. b->offset += sprintf(b->buffer + b->offset, " BAR4: 0x%8x", pci_read_field(device, PCI_BAR4, 4));
  546. b->offset += sprintf(b->buffer + b->offset, " BAR6: 0x%8x\n", pci_read_field(device, PCI_BAR5, 4));
  547. b->offset += sprintf(b->buffer + b->offset, " IRQ Line: %d", pci_read_field(device, 0x3C, 1));
  548. b->offset += sprintf(b->buffer + b->offset, " IRQ Pin: %d", pci_read_field(device, 0x3D, 1));
  549. b->offset += sprintf(b->buffer + b->offset, " Interrupt: %d", pci_get_interrupt(device));
  550. b->offset += sprintf(b->buffer + b->offset, " Status: 0x%4x\n", pci_read_field(device, PCI_STATUS, 2));
  551. }
  552. static void scan_count(uint32_t device, uint16_t vendorid, uint16_t deviceid, void * extra) {
  553. size_t * count = extra;
  554. (*count)++;
  555. }
  556. static uint32_t pci_func(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  557. size_t count = 0;
  558. pci_scan(&scan_count, -1, &count);
  559. struct _pci_buf b = {0,NULL};
  560. b.buffer = malloc(count * 1024);
  561. pci_scan(&scan_hit_list, -1, &b);
  562. size_t _bsize = b.offset;
  563. if (offset > _bsize) {
  564. free(b.buffer);
  565. return 0;
  566. }
  567. if (size > _bsize - offset) size = _bsize - offset;
  568. memcpy(buffer, b.buffer + offset, size);
  569. free(b.buffer);
  570. return size;
  571. }
  572. static struct procfs_entry std_entries[] = {
  573. {-1, "cpuinfo", cpuinfo_func},
  574. {-2, "meminfo", meminfo_func},
  575. {-3, "uptime", uptime_func},
  576. {-4, "cmdline", cmdline_func},
  577. {-5, "version", version_func},
  578. {-6, "compiler", compiler_func},
  579. {-7, "mounts", mounts_func},
  580. {-8, "modules", modules_func},
  581. {-9, "filesystems", filesystems_func},
  582. {-10,"loader", loader_func},
  583. {-11,"irq", irq_func},
  584. {-12,"pat", pat_func},
  585. {-13,"pci", pci_func},
  586. };
  587. static list_t * extended_entries = NULL;
  588. static int next_id = 0;
  589. int procfs_install(struct procfs_entry * entry) {
  590. if (!extended_entries) {
  591. extended_entries = list_create();
  592. next_id = -PROCFS_STANDARD_ENTRIES - 1;
  593. }
  594. entry->id = next_id--;
  595. list_insert(extended_entries, entry);
  596. return 0;
  597. }
  598. static struct dirent * readdir_procfs_root(fs_node_t *node, uint32_t index) {
  599. if (index == 0) {
  600. struct dirent * out = malloc(sizeof(struct dirent));
  601. memset(out, 0x00, sizeof(struct dirent));
  602. out->ino = 0;
  603. strcpy(out->name, ".");
  604. return out;
  605. }
  606. if (index == 1) {
  607. struct dirent * out = malloc(sizeof(struct dirent));
  608. memset(out, 0x00, sizeof(struct dirent));
  609. out->ino = 0;
  610. strcpy(out->name, "..");
  611. return out;
  612. }
  613. if (index == 2) {
  614. struct dirent * out = malloc(sizeof(struct dirent));
  615. memset(out, 0x00, sizeof(struct dirent));
  616. out->ino = 0;
  617. strcpy(out->name, "self");
  618. return out;
  619. }
  620. index -= 3;
  621. if (index < PROCFS_STANDARD_ENTRIES) {
  622. struct dirent * out = malloc(sizeof(struct dirent));
  623. memset(out, 0x00, sizeof(struct dirent));
  624. out->ino = std_entries[index].id;
  625. strcpy(out->name, std_entries[index].name);
  626. return out;
  627. }
  628. index -= PROCFS_STANDARD_ENTRIES;
  629. if (extended_entries) {
  630. if (index < extended_entries->length) {
  631. size_t i = 0;
  632. node_t * n = extended_entries->head;
  633. while (i < index) {
  634. n = n->next;
  635. i++;
  636. }
  637. struct procfs_entry * e = n->value;
  638. struct dirent * out = malloc(sizeof(struct dirent));
  639. memset(out, 0x00, sizeof(struct dirent));
  640. out->ino = e->id;
  641. strcpy(out->name, e->name);
  642. return out;
  643. }
  644. index -= extended_entries->length;
  645. }
  646. int i = index + 1;
  647. debug_print(WARNING, "%d %d %d", i, index, PROCFS_STANDARD_ENTRIES);
  648. pid_t pid = 0;
  649. foreach(lnode, process_list) {
  650. i--;
  651. if (i == 0) {
  652. process_t * proc = (process_t *)lnode->value;
  653. pid = proc->id;
  654. break;
  655. }
  656. }
  657. if (pid == 0) {
  658. return NULL;
  659. }
  660. struct dirent * out = malloc(sizeof(struct dirent));
  661. memset(out, 0x00, sizeof(struct dirent));
  662. out->ino = pid;
  663. sprintf(out->name, "%d", pid);
  664. return out;
  665. }
  666. static fs_node_t * finddir_procfs_root(fs_node_t * node, char * name) {
  667. if (!name) return NULL;
  668. if (strlen(name) < 1) return NULL;
  669. if (name[0] >= '0' && name[0] <= '9') {
  670. /* XXX process entries */
  671. pid_t pid = atoi(name);
  672. process_t * proc = process_from_pid(pid);
  673. if (!proc) {
  674. return NULL;
  675. }
  676. fs_node_t * out = procfs_procdir_create(proc);
  677. return out;
  678. }
  679. if (!strcmp(name,"self")) {
  680. return procfs_procdir_create((process_t *)current_process);
  681. }
  682. for (unsigned int i = 0; i < PROCFS_STANDARD_ENTRIES; ++i) {
  683. if (!strcmp(name, std_entries[i].name)) {
  684. fs_node_t * out = procfs_generic_create(std_entries[i].name, std_entries[i].func);
  685. return out;
  686. }
  687. }
  688. foreach(node, extended_entries) {
  689. struct procfs_entry * e = node->value;
  690. if (!strcmp(name, e->name)) {
  691. fs_node_t * out = procfs_generic_create(e->name, e->func);
  692. return out;
  693. }
  694. }
  695. return NULL;
  696. }
  697. static fs_node_t * procfs_create(void) {
  698. fs_node_t * fnode = malloc(sizeof(fs_node_t));
  699. memset(fnode, 0x00, sizeof(fs_node_t));
  700. fnode->inode = 0;
  701. strcpy(fnode->name, "proc");
  702. fnode->mask = 0555;
  703. fnode->uid = 0;
  704. fnode->gid = 0;
  705. fnode->flags = FS_DIRECTORY;
  706. fnode->read = NULL;
  707. fnode->write = NULL;
  708. fnode->open = NULL;
  709. fnode->close = NULL;
  710. fnode->readdir = readdir_procfs_root;
  711. fnode->finddir = finddir_procfs_root;
  712. fnode->nlink = 1;
  713. fnode->ctime = now();
  714. fnode->mtime = now();
  715. fnode->atime = now();
  716. return fnode;
  717. }
  718. int procfs_initialize(void) {
  719. /* TODO Move this to some sort of config */
  720. vfs_mount("/proc", procfs_create());
  721. debug_print_vfs_tree();
  722. return 0;
  723. }
  724. int procfs_finalize(void) {
  725. return 0;
  726. }
  727. MODULE_DEF(procfs, procfs_initialize, procfs_finalize);