procfs.c 23 KB

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