1+ #include "../fs/vfs.h"
2+ #include "../fs/gpt.h"
3+ #include "../fs/ext2.h"
4+ #include "../fs/fat32.h"
5+ #include "../../syslibc/stdio.h"
6+ #include "../../syslibc/string.h"
7+
8+ extern void term_print (const char * str );
9+ extern void ext2_set_partition (uint64_t lba );
10+ extern int ext2_format (uint64_t start_lba , uint64_t sector_count );
11+ extern void fat32_init (void );
12+
13+ // Вспомогательная функция для создания родительских директорий по пути (например, /mnt/target/bin)
14+ static void ensure_directory (const char * path ) {
15+ char temp [256 ];
16+ strncpy (temp , path , sizeof (temp ) - 1 );
17+ temp [sizeof (temp )- 1 ] = '\0' ;
18+
19+ // Отрезаем имя файла, оставляем только путь к папке
20+ char * last_slash = strrchr (temp , '/' );
21+ if (last_slash ) {
22+ * last_slash = '\0' ;
23+ // Если такой папки еще нет в VFS, создаем её рекурсивно
24+ if (!vfs_dir_exists (temp )) {
25+ // Если нужно, можно сделать mkdir для каждого уровня, но у нас плоская структура
26+ vfs_mkdir (temp );
27+ }
28+ }
29+ }
30+
31+ // Функция копирования файла средствами VFS
32+ int copy_file (const char * src , const char * dst ) {
33+ vfs_file_t * sf = vfs_open (src , VFS_O_RDONLY );
34+ if (!sf ) return -1 ;
35+
36+ // Гарантируем, что папка назначения существует
37+ ensure_directory (dst );
38+
39+ vfs_file_t * df = vfs_open (dst , VFS_O_WRONLY | VFS_O_CREAT | VFS_O_TRUNC );
40+ if (!df ) {
41+ vfs_close (sf );
42+ return -1 ;
43+ }
44+
45+ uint8_t buffer [4096 ];
46+ int bytes_read ;
47+ while ((bytes_read = vfs_read (sf , buffer , sizeof (buffer ))) > 0 ) {
48+ vfs_write (df , buffer , bytes_read );
49+ }
50+
51+ vfs_close (sf );
52+ vfs_close (df );
53+ return 0 ;
54+ }
55+
56+ void install_equinox_os (void ) {
57+ term_print ("\n=== EquinoxOS Universal Installer ===\n" );
58+
59+ // 1. Парсим GPT
60+ gpt_partition_t parts [GPT_MAX_PARTITIONS ];
61+ int part_count = gpt_parse (0 , parts , GPT_MAX_PARTITIONS );
62+ if (part_count < 0 ) {
63+ term_print ("Error: Could not parse GPT. Installation aborted.\n" );
64+ return ;
65+ }
66+
67+ // 2. Ищем ESP (FAT32)
68+ int esp_idx = gpt_find_esp (0 , parts , part_count );
69+ if (esp_idx == -1 ) {
70+ term_print ("Error: EFI System Partition (ESP) not found!\n" );
71+ return ;
72+ }
73+ gpt_partition_t * esp = & parts [esp_idx ];
74+
75+ // 3. Выбираем раздел под Root
76+ int root_idx = -1 ;
77+ for (int i = 0 ; i < part_count ; i ++ ) {
78+ if (i != esp_idx && parts [i ].size_sectors > 100000 ) {
79+ root_idx = i ;
80+ break ;
81+ }
82+ }
83+ if (root_idx == -1 ) {
84+ term_print ("Error: Target partition for OS Root not found!\n" );
85+ return ;
86+ }
87+ gpt_partition_t * root_part = & parts [root_idx ];
88+
89+ // 4. Форматируем Ext2 раздел под ОС
90+ ext2_format (root_part -> first_lba , root_part -> size_sectors );
91+
92+ // 5. Монтируем целевой раздел Ext2 в /mnt/target
93+ ext2_set_partition (root_part -> first_lba );
94+ vfs_node_t * ext2_root = ext2_get_root_node ();
95+ vfs_mount ("/mnt/target" , ext2_root );
96+
97+ // 6. Монтируем ESP (FAT32) в /mnt/esp
98+ fat32_init ();
99+ vfs_node_t * fat_root = fat32_get_root_node ();
100+ vfs_mount ("/mnt/esp" , fat_root );
101+
102+ // 7. Читаем манифест установки с загрузочной флешки
103+ vfs_file_t * manifest = vfs_open ("/etc/install_manifest.txt" , VFS_O_RDONLY );
104+ if (!manifest ) {
105+ term_print ("Error: /etc/install_manifest.txt not found! Installation aborted.\n" );
106+ return ;
107+ }
108+
109+ term_print ("Copying system files based on manifest...\n" );
110+
111+ char line_buf [256 ];
112+ int line_len = 0 ;
113+ char c ;
114+
115+ // Построчно читаем манифест
116+ while (vfs_read (manifest , & c , 1 ) == 1 ) {
117+ if (c == '\n' || c == '\r' ) {
118+ if (line_len > 0 ) {
119+ line_buf [line_len ] = '\0' ;
120+
121+ // Генерируем пути копирования
122+ // Источник: "/bin/sh.elf"
123+ // Назначение: "/mnt/target/bin/sh.elf"
124+ char dest_path [512 ];
125+ sprintf (dest_path , "/mnt/target%s" , line_buf );
126+
127+ char log_msg [512 ];
128+ sprintf (log_msg , " -> Copying: %s\n" , line_buf );
129+ term_print (log_msg );
130+
131+ if (copy_file (line_buf , dest_path ) != 0 ) {
132+ char err_msg [512 ];
133+ sprintf (err_msg , " [!] Error copying %s\n" , line_buf );
134+ term_print (err_msg );
135+ }
136+ line_len = 0 ;
137+ }
138+ } else if (line_len < 254 ) {
139+ line_buf [line_len ++ ] = c ;
140+ }
141+ }
142+ vfs_close (manifest );
143+
144+ // 8. Копируем файлы загрузчика Limine на ESP
145+ term_print ("Installing Limine Bootloader to ESP...\n" );
146+
147+ vfs_mkdir ("/mnt/esp/EFI" );
148+ vfs_mkdir ("/mnt/esp/EFI/BOOT" );
149+ vfs_mkdir ("/mnt/esp/res" );
150+ vfs_mkdir ("/mnt/esp/sys" );
151+
152+ copy_file ("/boot/limine/BOOTX64.EFI" , "/mnt/esp/EFI/BOOT/BOOTX64.EFI" );
153+ copy_file ("/sys/kernel.elf" , "/mnt/esp/sys/kernel.elf" );
154+ copy_file ("/res/BG.BMP" , "/mnt/esp/res/BG.BMP" );
155+
156+ // Записываем новый limine.conf для жесткого диска
157+ const char * new_limine_conf =
158+ "timeout: 3\n"
159+ "backdrop: ff0b1220\n"
160+ "term_background: ff0b1220\n"
161+ "term_foreground: ffffff\n"
162+ "term_wallpaper: boot():/res/BG.BMP\n"
163+ "wallpaper: boot():/res/BG.BMP\n"
164+ "/EquinoxOS\n"
165+ " protocol: limine\n"
166+ " path: boot():/sys/kernel.elf\n"
167+ " resolution: 1920x1080x32\n"
168+ " module_path: boot():/res/font.psf\n" ;
169+
170+ vfs_write_file ("/mnt/esp/EFI/BOOT/limine.conf" , (const uint8_t * )new_limine_conf , strlen (new_limine_conf ));
171+
172+ term_print ("\nInstallation complete! Please reboot.\n" );
173+ }
0 commit comments