3 #include <netinet/in.h>
9 #define ElfHeaderSize (64 * 1024)
10 #define ElfPages (ElfHeaderSize / 4096)
11 #define KERNELBASE (0xc0000000)
13 void get4k(FILE *file
, char *buf
)
16 unsigned num
= fread(buf
, 1, 4096, file
);
17 for ( j
=num
; j
<4096; ++j
)
21 void put4k(FILE *file
, char *buf
)
23 fwrite(buf
, 1, 4096, file
);
26 void death(const char *msg
, FILE *fdesc
, const char *fname
)
34 int main(int argc
, char **argv
)
38 FILE *inputVmlinux
= NULL
;
39 FILE *outputVmlinux
= NULL
;
41 u_int32_t ramFileLen
= 0;
44 u_int32_t kernelLen
= 0;
45 u_int32_t actualKernelLen
= 0;
47 u_int32_t roundedKernelLen
= 0;
48 u_int32_t ramStartOffs
= 0;
49 u_int32_t ramPages
= 0;
50 u_int32_t roundedKernelPages
= 0;
51 u_int32_t hvReleaseData
= 0;
52 u_int32_t eyeCatcher
= 0xc8a5d9c4;
54 u_int32_t xRamDisk
= 0;
55 u_int32_t xRamDiskSize
= 0;
57 printf("Name of RAM disk file missing.\n");
62 printf("Name of vmlinux file missing.\n");
67 printf("Name of vmlinux output file missing.\n");
71 ramDisk
= fopen(argv
[1], "r");
73 printf("RAM disk file \"%s\" failed to open.\n", argv
[1]);
76 inputVmlinux
= fopen(argv
[2], "r");
77 if ( ! inputVmlinux
) {
78 printf("vmlinux file \"%s\" failed to open.\n", argv
[2]);
81 outputVmlinux
= fopen(argv
[3], "w+");
82 if ( ! outputVmlinux
) {
83 printf("output vmlinux file \"%s\" failed to open.\n", argv
[3]);
86 fseek(ramDisk
, 0, SEEK_END
);
87 ramFileLen
= ftell(ramDisk
);
88 fseek(ramDisk
, 0, SEEK_SET
);
89 printf("%s file size = %d\n", argv
[1], ramFileLen
);
93 roundR
= 4096 - (ramLen
% 4096);
95 printf("Rounding RAM disk file up to a multiple of 4096, adding %d\n", roundR
);
99 printf("Rounded RAM disk size is %d\n", ramLen
);
100 fseek(inputVmlinux
, 0, SEEK_END
);
101 kernelLen
= ftell(inputVmlinux
);
102 fseek(inputVmlinux
, 0, SEEK_SET
);
103 printf("kernel file size = %d\n", kernelLen
);
104 if ( kernelLen
== 0 ) {
105 printf("You must have a linux kernel specified as argv[2]\n");
109 actualKernelLen
= kernelLen
- ElfHeaderSize
;
111 printf("actual kernel length (minus ELF header) = %d\n", actualKernelLen
);
113 round
= actualKernelLen
% 4096;
114 roundedKernelLen
= actualKernelLen
;
116 roundedKernelLen
+= (4096 - round
);
118 printf("actual kernel length rounded up to a 4k multiple = %d\n", roundedKernelLen
);
120 ramStartOffs
= roundedKernelLen
;
121 ramPages
= ramLen
/ 4096;
123 printf("RAM disk pages to copy = %d\n", ramPages
);
125 // Copy 64K ELF header
126 for (i
=0; i
<(ElfPages
); ++i
) {
127 get4k( inputVmlinux
, inbuf
);
128 put4k( outputVmlinux
, inbuf
);
131 roundedKernelPages
= roundedKernelLen
/ 4096;
133 fseek(inputVmlinux
, ElfHeaderSize
, SEEK_SET
);
135 for ( i
=0; i
<roundedKernelPages
; ++i
) {
136 get4k( inputVmlinux
, inbuf
);
137 put4k( outputVmlinux
, inbuf
);
140 for ( i
=0; i
<ramPages
; ++i
) {
141 get4k( ramDisk
, inbuf
);
142 put4k( outputVmlinux
, inbuf
);
145 /* Close the input files */
147 fclose(inputVmlinux
);
148 /* And flush the written output file */
149 fflush(outputVmlinux
);
151 /* fseek to the hvReleaseData pointer */
152 fseek(outputVmlinux
, ElfHeaderSize
+ 0x24, SEEK_SET
);
153 if (fread(&hvReleaseData
, 4, 1, outputVmlinux
) != 1) {
154 death("Could not read hvReleaseData pointer\n", outputVmlinux
, argv
[3]);
156 hvReleaseData
= ntohl(hvReleaseData
); /* Convert to native int */
157 printf("hvReleaseData is at %08x\n", hvReleaseData
);
159 /* fseek to the hvReleaseData */
160 fseek(outputVmlinux
, ElfHeaderSize
+ hvReleaseData
, SEEK_SET
);
161 if (fread(inbuf
, 0x40, 1, outputVmlinux
) != 1) {
162 death("Could not read hvReleaseData\n", outputVmlinux
, argv
[3]);
164 /* Check hvReleaseData sanity */
165 if (memcmp(inbuf
, &eyeCatcher
, 4) != 0) {
166 death("hvReleaseData is invalid\n", outputVmlinux
, argv
[3]);
168 /* Get the naca pointer */
169 naca
= ntohl(*((u_int32_t
*) &inbuf
[0x0c])) - KERNELBASE
;
170 printf("naca is at %08x\n", naca
);
172 /* fseek to the naca */
173 fseek(outputVmlinux
, ElfHeaderSize
+ naca
, SEEK_SET
);
174 if (fread(inbuf
, 0x18, 1, outputVmlinux
) != 1) {
175 death("Could not read naca\n", outputVmlinux
, argv
[3]);
177 xRamDisk
= ntohl(*((u_int32_t
*) &inbuf
[0x0c]));
178 xRamDiskSize
= ntohl(*((u_int32_t
*) &inbuf
[0x14]));
179 /* Make sure a RAM disk isn't already present */
180 if ((xRamDisk
!= 0) || (xRamDiskSize
!= 0)) {
181 death("RAM disk is already attached to this kernel\n", outputVmlinux
, argv
[3]);
183 /* Fill in the values */
184 *((u_int32_t
*) &inbuf
[0x0c]) = htonl(ramStartOffs
);
185 *((u_int32_t
*) &inbuf
[0x14]) = htonl(ramPages
);
187 /* Write out the new naca */
188 fflush(outputVmlinux
);
189 fseek(outputVmlinux
, ElfHeaderSize
+ naca
, SEEK_SET
);
190 if (fwrite(inbuf
, 0x18, 1, outputVmlinux
) != 1) {
191 death("Could not write naca\n", outputVmlinux
, argv
[3]);
193 printf("RAM Disk of 0x%x pages size is attached to the kernel at offset 0x%08x\n",
194 ramPages
, ramStartOffs
);
197 fclose(outputVmlinux
);
198 /* Set permission to executable */
199 chmod(argv
[3], S_IRUSR
|S_IWUSR
|S_IXUSR
|S_IRGRP
|S_IXGRP
|S_IROTH
|S_IXOTH
);