xref: /reactos/boot/freeldr/install/linux/finstext2.c (revision 0c2cdcae)
1 #include <stdio.h>
2 #include <string.h>
3 #include "finstext2.h"
4 #include "ext2.h"    // #defines ext2_data
5 #include <linux/hdreg.h>
6 #include <linux/ext3_fs.h>
7 #include <sys/ioctl.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 
13 #define MAJOR_VERSION    1
14 #define MINOR_VERSION    0
15 
16 PEXT2_BOOTCODE            Ext2BootCode = (PEXT2_BOOTCODE)ext2_data;
17 struct ext3_super_block    Ext2SuperBlock;
18 struct hd_geometry        Ext2DriveGeometry;
19 unsigned char            Ext2ExistingBootCode[1024];
20 
21 char                    BlockDevice[260];
22 int                        BlockDeviceSpecified = 0;
23 int                        BlockDeviceFileDescriptor;
24 
main(int argc,char * argv[])25 int main(int argc, char *argv[])
26 {
27     int        Index;
28     char    ch;
29 
30     // Verify that we got enough command line parameters
31     if (argc < 2)
32     {
33         printf("finstext2 block_device [-v]\n\n");
34         printf("block_device    Specifies the ext2/3 volume to install to (i.e. /dev/hda1)\n");
35         printf("-v              Displays the version\n\n");
36     }
37 
38     // Parse the command line parameters
39     for (Index=1; Index<argc; Index++)
40     {
41         if (strcmp(argv[Index], "-v") == 0)
42         {
43             printf("FreeLoader Ext2/3 Installer v%d.%d\n", MAJOR_VERSION, MINOR_VERSION);
44         }
45         else
46         {
47             strcpy(BlockDevice, argv[Index]);
48             BlockDeviceSpecified = 1;
49         }
50     }
51 
52     if (BlockDeviceSpecified)
53     {
54         BlockDeviceFileDescriptor = open(BlockDevice, O_RDWR|O_SYNC);
55 
56         if (BlockDeviceFileDescriptor == -1)
57         {
58             printf("Couldn't open block device %s\n", BlockDevice);
59             return 1;
60         }
61 
62         if (read(BlockDeviceFileDescriptor, Ext2ExistingBootCode, (size_t)1024) != (ssize_t)1024)
63         {
64             close(BlockDeviceFileDescriptor);
65             printf("Couldn't read existing boot code from %s\n", BlockDevice);
66             return 1;
67         }
68 
69         for (Index=0; Index<1024; Index++)
70         {
71             if (Ext2ExistingBootCode[Index] != 0x00)
72             {
73                 printf("This EXT2/3 volume has existing boot code.\n");
74                 printf("Do you want to overwrite it? [y/n] ");
75                 scanf("%c", &ch);
76 
77                 if (ch == 'n' || ch == 'N')
78                 {
79                     close(BlockDeviceFileDescriptor);
80                     printf("Cancelled.\n");
81                     return 0;
82                 }
83 
84                 break;
85             }
86         }
87 
88         if (read(BlockDeviceFileDescriptor, &Ext2SuperBlock, (size_t)1024) != (ssize_t)1024)
89         {
90             close(BlockDeviceFileDescriptor);
91             printf("Couldn't read super block from %s\n", BlockDevice);
92             return 1;
93         }
94 
95         if (Ext2SuperBlock.s_magic != EXT3_SUPER_MAGIC)
96         {
97             close(BlockDeviceFileDescriptor);
98             printf("Block device %s is not a EXT2/3 volume or has an invalid super block.\n", BlockDevice);
99             return 1;
100         }
101 
102         if (ioctl(BlockDeviceFileDescriptor, HDIO_GETGEO, &Ext2DriveGeometry) != 0)
103         {
104             close(BlockDeviceFileDescriptor);
105             printf("Couldn't get drive geometry from block device %s\n", BlockDevice);
106             return 1;
107         }
108 
109         printf("Heads: %d\n", Ext2DriveGeometry.heads);
110         printf("Sectors: %d\n", Ext2DriveGeometry.sectors);
111         printf("Cylinders: %d\n", Ext2DriveGeometry.cylinders);
112         printf("Start: %d\n", Ext2DriveGeometry.start);
113 
114         Ext2BootCode->BootDrive = 0xff;
115         Ext2BootCode->BootPartition = 0x00;
116         //Ext2BootCode->SectorsPerTrack = Ext2DriveGeometry.sectors;
117         //Ext2BootCode->NumberOfHeads = Ext2DriveGeometry.heads;
118         Ext2BootCode->Ext2VolumeStartSector = Ext2DriveGeometry.start;
119         Ext2BootCode->Ext2BlockSizeInBytes = 1024 << Ext2SuperBlock.s_log_block_size;
120         Ext2BootCode->Ext2BlockSize = Ext2BootCode->Ext2BlockSizeInBytes / 512;
121         Ext2BootCode->Ext2PointersPerBlock = Ext2BootCode->Ext2BlockSizeInBytes / 4;
122         Ext2BootCode->Ext2GroupDescPerBlock = Ext2BootCode->Ext2BlockSizeInBytes / 32;
123         Ext2BootCode->Ext2FirstDataBlock = Ext2SuperBlock.s_first_data_block;
124         Ext2BootCode->Ext2InodesPerGroup = Ext2SuperBlock.s_inodes_per_group;
125         Ext2BootCode->Ext2InodesPerBlock = Ext2BootCode->Ext2BlockSizeInBytes / 128;
126 
127         if (lseek(BlockDeviceFileDescriptor, (off_t)0, SEEK_SET) == (off_t)-1)
128         {
129             close(BlockDeviceFileDescriptor);
130             printf("Couldn't write boot code on %s\n", BlockDevice);
131             return 1;
132         }
133 
134         if (write(BlockDeviceFileDescriptor, Ext2BootCode, (size_t)1024) != (ssize_t)1024)
135         {
136             close(BlockDeviceFileDescriptor);
137             printf("Couldn't write boot code on %s\n", BlockDevice);
138             return 1;
139         }
140 
141         close(BlockDeviceFileDescriptor);
142 
143         printf("Boot code written successfully!\n");
144     }
145 
146     return 0;
147 }
148