11 #include <sys/variable.h>
15 #include "io/status_loggers.h"
17 #include "lib/split.h"
19 #include "drv/input/keyboard.h"
20 #include "lib/php/explode.h"
23 #include "sys/scheduler.h"
24 #include "sys/timer.h"
25 #include "drv/disk/dpm.h"
27 #include "sys/pixfmt.h"
28 #include "io/rgb_image.h"
29 #include <sys/cpuinfo.h>
30 #include "../../include/lib/fileio.h"
31 #include "sys/system.h"
32 #include "debug/hexview.h"
33 #include "lib/command_parser.h"
35 #include "../ports/eBat/eBat.h"
36 #include "../ports/eBat/eBatRuntime.h"
38 int G_CLI_CURINXA = 0;
39 int G_CLI_CURINXB = 0;
42 char G_CLI_PATH[1024] =
"R:\\Sayori\\";
47 uint32_t (*funcv)(uint32_t,
char**);
78 uint32_t CLI_CMD_CLS(uint32_t c,
char* v[]){
83 uint32_t CLI_CMD_SYSINFO(uint32_t c,
char* v[]){
88 tty_printf(
"SayoriOS by SayoriOS Team (pimnik98 and NDRAEY)\n\n");
90 tty_printf(
"Системная информация:\n");
91 tty_printf(
"\tOS: SayoriOS v%d.%d.%d\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
92 tty_printf(
"\tДата сборки: %s\n", __TIMESTAMP__);
93 tty_printf(
"\tАрхитектура: %s\n", ARCH_TYPE);
96 if(is_temperature_module_present()) {
97 tty_printf(
"\tТемпература: %d *C\n", get_cpu_temperature());
99 tty_printf(
"\tТемпература: -- *C\n");
102 tty_printf(
"\tОЗУ: %u kb\n", getInstalledRam()/1024);
103 tty_printf(
"\tВидеоадаптер: %s\n",
"Legacy framebuffer (Unknown)");
104 tty_printf(
"\tДисплей: %s (%dx%d)\n",
"(\?\?\?)", getScreenWidth(), getScreenHeight());
105 tty_printf(
"\tТики: %d\n",
getTicks());
106 tty_printf(
"\tЧастота таймера: %d Гц\n",
getFrequency());
107 tty_printf(
"\tВремя с момента запуска: %f секунд\n", getUptime());
112 uint32_t CLI_CMD_DISKPART(uint32_t c,
char* v[]){
113 _tty_printf(
"Список примонтированных дисков:\n");
115 for(
int i = 0; i < 26; i++){
116 DPM_Disk dpm = dpm_info(i + 65);
117 if (dpm.Ready != 1)
continue;
118 _tty_printf(
" [%c] %s | %s\n", i + 65, dpm.FileSystem, dpm.Name);
127 uint32_t CLI_CMD_CAT(uint32_t c,
char* v[]){
128 if (c == 0 || (c == 1 && (
strcmpn(v[1],
"/?")))){
129 _tty_printf(
"Данная программа выводит содержимое файла.\n");
130 _tty_printf(
"Пример:\"CAT R:\\Sayori\\motd\".\n");
137 tty_printf(
"[CMD] [CAT] Не удалось найти файл `%s`. Проверьте правильность введенного вами пути.\n",v[1]);
143 uint8_t* buffer = kcalloc(1,
filesize + 1);
147 tty_printf(
"%s", buffer);
155 uint32_t CLI_CMD_DEL(uint32_t c,
char* v[]){
156 if (c == 0 || (c == 1 && (
strcmpn(v[1],
"/?")))){
157 _tty_printf(
"Удаление файла\n");
158 _tty_printf(
"Пример:\"DEL T:\\Sayori\\tmp.log\".\n");
167 tty_printf(
"Не удалось удалить файл, возможно файл не найден или у вас недостаточно прав для его удаления.\n");
174 uint32_t CLI_CMD_RMDIR(uint32_t c,
char* v[]){
175 if (c == 0 || (c == 1 && (
strcmpn(v[1],
"/?")))){
176 _tty_printf(
"Удаление папки\n");
177 _tty_printf(
"Пример:\"RMDIR T:\\Sayori\\\".\n");
182 bool res =
rmdir(v[1]);
186 tty_printf(
"Не удалось удалить папку, возможно папка не найдена или у вас недостаточно прав для её удаления.\n");
192 uint32_t CLI_CMD_TOUCH(uint32_t c,
char* v[]){
193 if (c == 0 || (c == 1 && (
strcmpn(v[1],
"/?")))){
194 _tty_printf(
"Создание файла\n");
195 _tty_printf(
"Пример:\"TOUCH T:\\Sayori\\tmp.log\".\n");
200 bool res =
touch(v[1]);
204 tty_printf(
"Не удалось создать файл, возможно файл уже существует или у вас недостаточно прав для её создания в этой папке.\n");
210 uint32_t CLI_CMD_MKDIR(uint32_t c,
char* v[]){
211 if (c == 0 || (c == 1 && (
strcmpn(v[1],
"/?")))){
212 _tty_printf(
"Создание папки\n");
213 _tty_printf(
"Пример:\"TOUCH T:\\Sayori\\\".\n");
218 bool res =
mkdir(v[1]);
222 tty_printf(
"Не удалось создать папка, возможно папка уже существует или у вас недостаточно прав для её создания в этой папке.\n");
228 uint32_t CLI_CMD_JSE(uint32_t c,
char* v[]){
229 if (c == 0 || (c == 1 && (
strcmpn(v[1],
"/?")))){
230 _tty_printf(
"JavaScript Engine.\n");
231 _tty_printf(
"Пример:\"JSE R:\\jse\\console.js\".\n");
236 int res = elk_file(v[1]);
240 tty_printf(
" [JSE] Произошла ошибка при выполнении скрипта. Подробности отправлены в консоль.");
246 if (c == 1 && (
strcmpn(v[1],
"/?"))){
247 _tty_printf(
"Для получения данных переменной введите \"SET ПЕРЕМЕННАЯ\".\n");
248 _tty_printf(
"Для установки переменной введите \"SET ПЕРЕМЕННАЯ=ЗНАЧЕНИЕ\".\n");
249 _tty_printf(
"Для удаления переменной введите \"SET ПЕРЕМЕННАЯ=\".\n\n");
256 for(
size_t i = 0; i<512; i++) {
257 if (s[i].Ready != 1)
break;
258 _tty_printf(
"%s=%s\n", s[i].Key, s[i].Value);
263 char** out = explode(v[1],
'=');
267 qemu_log(
"[Режим поиска] %s",v[1]);
269 for(
size_t i = 0; i<512; i++) {
270 if (s[i].Ready != 1)
break;
271 _tty_printf(
"%s=%s\n", s[i].Key, s[i].Value);
274 }
else if (out[1] == NULL ||
strlen(out[1]) == 0) {
275 qemu_log(
"[Режим удаления] %s",out[0]);
276 variable_write(out[0],
"");
277 }
else if (out[1] != NULL) {
278 qemu_log(
"[Режим изменения] %s",out[0]);
279 variable_write(out[0],out[1]);
294 const char* path = (c == 1 ? G_CLI_PATH : v[1]);
296 FSM_DIR* Dir = nvfs_dir(path);
297 if (Dir->Ready != 1){
298 tty_printf(
"Ошибка %d! При чтении папки: %s\n",Dir->Ready, path);
302 tty_printf(
"Содержимое папки папки: %s\n\n", path);
304 for (
int i = 0; i < Dir->Count; i++){
305 char* btime = fsm_timePrintable(Dir->Files[i].LastTime);
306 tty_printf(
"%s\t%s\t\t%s\n",
308 (Dir->Files[i].Type == 5?
"<ПАПКА>":
"<ФАЙЛ> "),
311 Sizes += Dir->Files[i].Size;
314 tty_printf(
"\nФайлов: %d | Папок: %d | Всего: %d\n", Dir->CountFiles, Dir->CountDir, Dir->Count);
315 tty_printf(
"Размер папки: %d мб. | %d кб. | %d б.\n", (Sizes != 0?(Sizes/1024/1024):0), (Sizes != 0?(Sizes/1024):0), Sizes);
324 uint32_t CLI_CMD_RUN(uint32_t c,
char* v[]) {
327 tty_printf(
"Файл не указан.\n");
331 const char* path = v[0];
337 tty_error(
"\"%s\" не является внутренней или внешней\n командой, исполняемой программой или пакетным файлом.\n", path);
341 if(!is_elf_file(elf_exec)) {
343 tty_printf(
"\"%s\" не является программой или данный тип файла не поддерживается.\n", path);
349 run_elf_file(path, c, v);
355 if (c == 1 && (
strcmpn(v[1],
"/?"))){
356 _tty_printf(
"Данная команда выводит сообщение на экран, а также переменные.\n");
360 for (
int i = 1; i <= c;i++){
362 size_t len_v =
strlen(v[i]);
363 size_t len_e = len_v-1;
364 if (v[i][0] ==
'%' && v[i][len_e] ==
'%'){
365 char* tmp_ve = kmalloc(len_v);
366 substr(tmp_ve,v[i],1,len_e-1);
367 char* tmp_dv = variable_read(tmp_ve);
369 if (tmp_dv != NULL) {
370 _tty_printf(
"%s",tmp_dv);
376 _tty_printf(
"2023-01-01");
378 _tty_printf(
"%s",G_CLI_PATH);
381 _tty_printf(
"%u", rand());
383 _tty_printf(
"%s",
"12:34");
385 _tty_printf(
"%s ", v[i]);
393 _tty_printf(
"Для получения дополнительной информации, наберите \"команда /?\", если справка по команде есть, она будет отображена.\n\n");
394 size_t hlp_padding = 11;
395 for(
size_t i = 0; G_CLI_CMD[i].name !=
nullptr; i++) {
396 _tty_printf(
"%s", G_CLI_CMD[i].name);
397 for(
size_t j = 0; j < hlp_padding -
strlen(G_CLI_CMD[i].name); j++) {
400 _tty_printf(
" | %s\n", G_CLI_CMD[i].helpstring);
410 uint32_t gfxbench(uint32_t argc,
char* args[]);
411 uint32_t miniplay(uint32_t argc,
char* args[]);
412 uint32_t CLI_CMD_NET(uint32_t c,
char **v);
413 uint32_t parallel_desktop_start(uint32_t argc,
char* args[]);
414 uint32_t mala_draw(uint32_t argc,
char* argv[]);
415 uint32_t pci_print_list(uint32_t argc,
char* argv[]);
417 uint32_t rust_command(uint32_t argc,
char* argv[]);
418 uint32_t CLI_MEMINFO(uint32_t argc,
char* argv[]) {
419 tty_printf(
"Физическая:\n");
420 tty_printf(
" Используется: %u байт (%u MB)\n", used_phys_memory_size, used_phys_memory_size / MB);
421 tty_printf(
" Свободно: %u байт (%u MB)\n", phys_memory_size - used_phys_memory_size, (phys_memory_size - used_phys_memory_size) / MB);
422 tty_printf(
"Виртуальная:\n");
423 tty_printf(
" %u записей\n", system_heap.allocated_count);
424 tty_printf(
" Используется: %u байт (%u MB)\n", system_heap.used_memory, system_heap.used_memory / MB);
429 uint32_t proc_list(uint32_t argc,
char* argv[]) {
438 process_t* proc = (process_t*)item;
440 tty_printf(
" Процесс: %d [%s]\n", proc->pid, proc->name);
449 thread_t* thread = (thread_t*)item_thread;
451 tty_printf(
" Поток: #%u процесса #%u; Стек: (%x, %x, %d); Состояние: %s\n",
452 thread->id, thread->process->pid, thread->stack_top, thread->stack, thread->stack_size,
453 thread_state_string(thread->state)
456 item_thread = item_thread->next;
462 uint32_t CLI_CMD_REBOOT(uint32_t argc,
char* argv[]) {
469 uint32_t CLI_SPAWN(uint32_t argc,
char* argv[]) {
470 qemu_log(
"SPAWN! %u", argc);
473 tty_printf(
"Файл не указан.\n");
477 const char* path = argv[1];
483 tty_error(
"\"%s\" не является внутренней или внешней\n командой, исполняемой программой или пакетным файлом.\n", path);
487 if(!is_elf_file(elf_exec)) {
489 tty_printf(
"\"%s\" не является программой или данный тип файла не поддерживается.\n", path);
495 spawn(path, argc, argv);
500 uint32_t CLI_SPAWN_TEST(uint32_t argc,
char* argv[]) {
501 char* cmdline[] = {
"hello"};
503 spawn(
"R:\\prog", 0, cmdline);
505 spawn(
"R:\\hellors", 0, cmdline);
510 uint32_t CLI_CMD_MTRR(uint32_t argc,
char* argv[]) {
516 uint32_t CLI_RD(uint32_t argc,
char* argv[]) {
518 tty_error(
"No arguments.\n");
522 char* disk = argv[1];
523 DPM_Disk data = dpm_info(disk[0]);
526 tty_error(
"No disk.\n");
530 char* newdata = kcalloc(1024, 1);
532 dpm_read(disk[0], 0, 0, 1024, newdata);
534 hexview_advanced(newdata, 1024, 26,
true, _tty_printf);
543 uint32_t CLI_CMD_HEX(uint32_t argc,
char** argv) {
545 tty_printf(
"No arguments\n");
549 char* file = argv[1];
554 tty_error(
"Failed to open file: %s\n", file);
558 size_t sz =
fsize(fp);
560 char* data = kcalloc(512, 1);
562 fread(fp, 512, 1, data);
564 tty_printf(
"Showing first 512 bytes:\n");
566 hexview_advanced(data, 512, 26,
true, _tty_printf);
574 uint32_t CLI_PLAIN(uint32_t argc,
char** argv) {
576 tty_error(
"plain <address> <file>");
577 tty_printf(
"Note: Address must be in HEX without 0x prefix! Example: CAFEBABE");
581 size_t address = htoi(argv[1]);
583 qemu_note(
"Address is: %x", address);
589 qemu_note(
"File size is: %d",
filesize);
591 void* a = kmalloc_common(ALIGN(
filesize, PAGE_SIZE), PAGE_SIZE);
594 size_t a_phys = virt2phys(get_kernel_page_directory(), (virtual_addr_t)a);
596 map_pages(get_kernel_page_directory(), (physical_addr_t)a_phys, address, ALIGN(
filesize, PAGE_SIZE), PAGE_WRITEABLE);
600 int (*entry)(int,
char**) = (
int(*)(int,
char**))address;
602 qemu_log(
"RESULT IS: %d", entry(0, 0));
604 unmap_pages_overlapping(get_kernel_page_directory(), address,
filesize);
612 uint32_t pavi_view(uint32_t,
char**);
613 uint32_t minesweeper(uint32_t,
char**);
614 uint32_t shell_diskctl(uint32_t,
char**);
615 uint32_t calendar(uint32_t,
char**);
616 uint32_t forth_sys(uint32_t,
char**);
619 {
"CLS",
"cls", CLI_CMD_CLS,
"Очистка экрана"},
620 {
"CALENDAR",
"calendar", calendar,
"Календарь"},
621 {
"CAT",
"cat", CLI_CMD_CAT,
"Выводит содержимое файла на экран"},
622 {
"ECHO",
"echo",
CLI_CMD_ECHO,
"Выводит сообщение на экран."},
623 {
"DIR",
"dir",
CLI_CMD_DIR,
"Выводит список файлов и папок."},
624 {
"DISKCTL",
"diskctl", shell_diskctl,
"Управление ATA-дисками"},
625 {
"DISKPART",
"diskpart", CLI_CMD_DISKPART,
"Список дисков Disk Partition Manager"},
627 {
"HELP",
"help", CLI_CMD_HELP,
"Выводит справочную информацию о командах SayoriOS (CLI)."},
628 {
"SET",
"set",
CLI_CMD_SET,
"Показывает, указывает и удаляет переменные среды SayoriOS"},
629 {
"NET",
"net", CLI_CMD_NET,
"Информация об сетевых устройствах"},
630 {
"GFXBENCH",
"gfxbench", gfxbench,
"Тестирование скорости фреймбуфера"},
631 {
"MEMINFO",
"meminfo", CLI_MEMINFO,
"Информация об оперативной памяти"},
632 {
"MINIPLAY",
"miniplay", miniplay,
"WAV-проиграватель"},
633 {
"DESKTOP",
"desktop", parallel_desktop_start,
"Рабочий стол"},
634 {
"MALA",
"mala", mala_draw,
"Нарисовать рисунок"},
635 {
"MINESWEEPER",
"minesweeper", minesweeper,
"Сапёр"},
636 {
"MTRR",
"mtrr", CLI_CMD_MTRR,
"MTRR"},
637 {
"PAVI",
"pavi", pavi_view,
"Программа для просмотра изображений"},
638 {
"PCI",
"pci", pci_print_list,
"Список PCI устройств"},
640 {
"PROC",
"proc", proc_list,
"Список процессов"},
641 {
"SYSINFO",
"sysinfo", CLI_CMD_SYSINFO,
"Информация о системе"},
642 {
"JSE",
"jse", CLI_CMD_JSE,
"JavaScript Engine"},
643 {
"TOUCH",
"touch", CLI_CMD_TOUCH,
"Создать файл"},
644 {
"DEL",
"DEL", CLI_CMD_DEL,
"Удалить файл"},
645 {
"MKDIR",
"mkdir", CLI_CMD_MKDIR,
"Создать папку"},
646 {
"RMDIR",
"rmdir", CLI_CMD_RMDIR,
"Удалить папку"},
647 {
"REBOOT",
"reboot", CLI_CMD_REBOOT,
"Перезагрузка"},
648 {
"RD",
"rd", CLI_RD,
"Чтение данных с диска"},
649 {
"SPAWN",
"spawn", CLI_SPAWN,
"spawn a new process"},
650 {
"PLAIN",
"plain", CLI_PLAIN,
"Run plain program"},
651 {
"HEX",
"hex", CLI_CMD_HEX,
"Show hex data"},
652 {
"ST",
"st", CLI_SPAWN_TEST,
"spawn test"},
653 {
"FORTH",
"forth",forth_sys,
"Форт система"},
654 {
"4TH",
"4th",forth_sys,
"Форт система"},
655 {
nullptr,
nullptr,
nullptr}
658 int cli_handler_ebat(
int argc,
char** argv){
659 qemu_note(
"[RUNTIME] [System] [EXEC] Count: %d\n", argc);
663 for(
size_t i = 0; G_CLI_CMD[i].name !=
nullptr; i++) {
664 if(
strcmpn(G_CLI_CMD[i].name, argv[0]) ||
strcmpn(G_CLI_CMD[i].alias, argv[0])) {
665 ret = G_CLI_CMD[i].funcv(argc, argv);
672 ret = CLI_CMD_RUN(argc, argv);
678 void cli_handler(
const char* ncmd){
679 set_cursor_enabled(0);
683 command_parser_new(&parser, ncmd);
685 for(
size_t i = 0; i < parser.argc; i++){
686 qemu_log(
"[CLI] '%s' => argc: %d => argv: %s", ncmd, i, parser.argv[i]);
691 for(
size_t i = 0; G_CLI_CMD[i].name !=
nullptr; i++) {
692 if(
strcmpn(G_CLI_CMD[i].name, parser.argv[0]) ||
strcmpn(G_CLI_CMD[i].alias, parser.argv[0])) {
693 G_CLI_CMD[i].funcv(parser.argc, parser.argv);
700 CLI_CMD_RUN(parser.argc, parser.argv);
703 command_parser_destroy(&parser);
705 set_cursor_enabled(1);
709 qemu_log(
"[CLI] Started...");
716 _tty_printf(
"SayoriOS [Версия: v%d.%d.%d]\n",VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
717 _tty_printf(
"(c) SayoriOS Team, 2023.\nДля дополнительной информации наберите \"help\".\n\n");
721 char* input_buffer = kcalloc(1, 512);
723 size_t memory_cur = system_heap.used_memory;
724 size_t memory_cnt_cur = system_heap.allocated_count;
727 tty_printf(
"%s>", G_CLI_PATH);
728 memset(input_buffer, 0, 512);
730 int result = gets_max(input_buffer, 512);
733 tty_alert(
"\nMaximum 512 characters!\n");
737 size_t len_cmd =
strlen(input_buffer);
742 size_t current_time = timestamp();
743 qemu_log(
"cmd: %s", input_buffer);
747 int preprocessor = 0;
749 if (preprocessor == 0){
750 cli_handler(input_buffer);
752 BAT_T* token = bat_parse_string(input_buffer);
755 int ret = bat_runtime_exec(token);
756 qemu_warn(
"RETURN CODE: %d\n",ret);
764 ssize_t delta = (int)system_heap.used_memory - (
int)memory_cur;
765 ssize_t delta_blocks = (int)system_heap.allocated_count - (
int)memory_cnt_cur;
766 qemu_warn(
"Used memory before: %d (%d blocks)", memory_cur, memory_cnt_cur);
767 qemu_warn(
"Used memory now: %d (%d blocks)", system_heap.used_memory, system_heap.allocated_count);
768 qemu_warn(
"Memory used: %d (%d blocks)", delta, delta_blocks);
771 qemu_err(
"Memory leak!");
772 }
else if(delta == 0) {
773 qemu_ok(
"All right! No memory leaks! Keep it up, buddy!");
776 qemu_note(
"Time elapsed: %d milliseconds", timestamp() - current_time);
int G_CLI_CURINXD
Текущий диск
uint32_t CLI_CMD_DIR(uint32_t c, char *v[])
uint32_t CLI_CMD_ECHO(uint32_t c, char *v[])
uint32_t CLI_CMD_SET(uint32_t c, char *v[])
struct registers __attribute__((packed))
Структура данных пакета от мыши
char * getNameBrand()
Получение имени процессора
size_t dpm_read(char Letter, uint64_t high_offset, uint64_t low_offset, size_t Size, void *Buffer)
[DPM] Считывание данных с диска
uint32_t str_cdsp2(const char *a_str, char del)
Функция отладки
bool mkdir(const char *Path)
[FileIO] Создает папку
bool unlink(const char *Path)
[FileIO] Удаляет файл
size_t filesize(const char *Path)
[FileIO] Возвращает размер указанного файла
bool rmdir(const char *Path)
[FileIO] Удаляет папку
bool touch(const char *Path)
[FileIO] Создает файл
size_t strlen(const char *str)
Возращает длину строки
bool strcmpn(const char *str1, const char *str2)
Сравнение строк
void * memset(void *ptr, char value, size_t num)
Заполнение массива указанными символами
void substr(char *restrict dest, const char *restrict source, int from, int length)
Вырезает и возвращает подстроку из строки
list_t process_list
Список процессов
list_t thread_list
Список потоков
void fclose(FILE *stream)
Закончить работу с файлом
FILE * fopen(const char *filename, const char *_mode)
Открывает файл
int fsize(FILE *stream)
Получение размера файла в байтах
int fread(FILE *stream, size_t count, size_t size, void *buffer)
Чтение файла
Структура файла. Требуется для работы с VFS.
void reboot()
Перезагрузка устройства
size_t getFrequency()
Получить частоту таймера
size_t getTicks()
Получить количество тиков
void sleep_ms(uint32_t milliseconds)
Ожидание по миллисекундам
void setPosY(uint32_t y)
Изменяем позицию курсора по Y.
void tty_set_bgcolor(uint32_t color)
Изменение цвета заднего фона
void tty_setcolor(uint32_t color)
Изменение цвета текста