grub2: bring back build of aros-side grub2 tools
[AROS.git] / tools / adflib / adf_raw.c
blob95a51b3b908f8c2f7774eb97e102243c4b3f95f5
1 /*
2 * ADF Library. (C) 1997-1998 Laurent Clevy
4 * adf_raw.c
6 * logical disk/volume code
7 */
9 #include <stdio.h>
10 #include <limits.h>
11 #include <stdlib.h>
12 #include <string.h>
14 #include "adf_str.h"
15 #include "adf_raw.h"
16 #include "adf_blk.h"
17 #include "adf_disk.h"
18 #include "adf_util.h"
19 #include "adf_err.h"
20 #include "defendian.h"
22 extern struct Env adfEnv;
24 int swapTable[MAX_SWTYPE+1][15]={
25 { 4, SW_CHAR, 2, SW_LONG, 1012, SW_CHAR, 0, 1024 }, /* first bytes of boot */
26 { 108, SW_LONG, 40, SW_CHAR, 10, SW_LONG, 0, 512 }, /* root */
27 { 6, SW_LONG, 488, SW_CHAR, 0, 512 }, /* data */
28 /* file, dir, entry */
29 { 82, SW_LONG, 92, SW_CHAR, 3, SW_LONG, 36, SW_CHAR, 11, SW_LONG, 0, 512 },
30 { 6, SW_LONG, 0, 24 }, /* cache */
31 { 128, SW_LONG, 0, 512 }, /* bitmap, fext */
32 /* link */
33 { 6, SW_LONG, 64, SW_CHAR, 86, SW_LONG, 32, SW_CHAR, 12, SW_LONG, 0, 512 },
34 { 4, SW_CHAR, 39, SW_LONG, 56, SW_CHAR, 10, SW_LONG, 0, 256 }, /* RDSK */
35 { 4, SW_CHAR, 127, SW_LONG, 0, 512 }, /* BADB */
36 { 4, SW_CHAR, 8, SW_LONG, 32, SW_CHAR, 31, SW_LONG, 4, SW_CHAR, /* PART */
37 15, SW_LONG, 0, 256 },
38 { 4, SW_CHAR, 7, SW_LONG, 4, SW_CHAR, 55, SW_LONG, 0, 256 }, /* FSHD */
39 { 4, SW_CHAR, 4, SW_LONG, 492, SW_CHAR, 0, 512 }, /* LSEG */
40 { 4, SW_CHAR, 4, SW_LONG, 492, SW_CHAR, 0, 512 } /* BOOT */
45 * swapEndian
47 * magic :-) endian swap function (big -> little for read, little to big for write)
50 void
51 swapEndian( UBYTE *buf, int type )
53 int i,j;
54 int p;
56 i=0;
57 p=0;
59 if (type>MAX_SWTYPE || type<0)
60 adfEnv.eFct("SwapEndian: type do not exist");
62 while( swapTable[type][i]!=0 ) {
63 for(j=0; j<swapTable[type][i]; j++) {
64 switch( swapTable[type][i+1] ) {
65 case SW_LONG:
66 *(ULONG*)(buf+p)=Long(buf+p);
67 p+=4;
68 break;
69 case SW_SHORT:
70 *(USHORT*)(buf+p)=Short(buf+p);
71 p+=2;
72 break;
73 case SW_CHAR:
74 p++;
75 break;
76 default:
80 i+=2;
82 if (p!=swapTable[type][i+1])
83 (*adfEnv.wFct)("Warning: Endian Swapping length\n");
93 * adfReadRootBlock
95 * ENDIAN DEPENDENT
97 RETCODE
98 adfReadRootBlock(struct Volume* vol, ULONG nSect, struct bRootBlock* root)
100 unsigned char buf[LOGICAL_BLOCK_SIZE];
102 if (adfReadBlock(vol, nSect, buf)!=RC_OK)
103 return RC_ERROR;
105 memcpy(root, buf, LOGICAL_BLOCK_SIZE);
106 #ifdef LITT_ENDIAN
107 swapEndian((unsigned char*)root, SWBL_ROOT);
108 #endif
110 if (root->type!=T_HEADER || root->secType!=ST_ROOT) {
111 (*adfEnv.wFct)("adfReadRootBlock : id not found");
112 return RC_ERROR;
114 if (root->checkSum!=adfNormalSum(buf, 20, LOGICAL_BLOCK_SIZE)) {
115 (*adfEnv.wFct)("adfReadRootBlock : invalid checksum");
116 return RC_ERROR;
119 return RC_OK;
124 * adfWriteRootBlock
128 RETCODE adfWriteRootBlock(struct Volume* vol, ULONG nSect, struct bRootBlock* root)
130 unsigned char buf[LOGICAL_BLOCK_SIZE];
131 ULONG newSum;
134 root->type = T_HEADER;
135 root->headerKey = 0L;
136 root->highSeq = 0L;
137 root->hashTableSize = HT_SIZE;
138 root->firstData = 0L;
139 /* checkSum, hashTable */
140 /* bmflag */
141 /* bmPages, bmExt */
142 root->nextSameHash = 0L;
143 root->parent = 0L;
144 root->secType = ST_ROOT;
146 memcpy(buf, root, LOGICAL_BLOCK_SIZE);
148 #ifdef LITT_ENDIAN
149 swapEndian(buf, SWBL_ROOT);
150 #endif
152 newSum = adfNormalSum(buf,20,LOGICAL_BLOCK_SIZE);
153 swLong(buf+20, newSum);
155 // dumpBlock(buf);
156 if (adfWriteBlock(vol, nSect, buf)!=RC_OK)
157 return RC_ERROR;
158 //printf("adfWriteRootBlock %ld\n",nSect);
159 return RC_OK;
164 * adfReadBootBlock
166 * ENDIAN DEPENDENT
168 RETCODE
169 adfReadBootBlock(struct Volume* vol, struct bBootBlock* boot)
171 unsigned char buf[1024];
173 //puts("22");
174 if (adfReadBlock(vol, 0, buf)!=RC_OK)
175 return RC_ERROR;
176 //puts("11");
177 if (adfReadBlock(vol, 1, buf+LOGICAL_BLOCK_SIZE)!=RC_OK)
178 return RC_ERROR;
180 memcpy(boot, buf, LOGICAL_BLOCK_SIZE*2);
181 #ifdef LITT_ENDIAN
182 swapEndian((unsigned char*)boot,SWBL_BOOTBLOCK);
183 #endif
184 if ( strncmp("DOS",boot->dosType,3)!=0 ) {
185 (*adfEnv.wFct)("adfReadBootBlock : DOS id not found");
186 return RC_ERROR;
189 if ( boot->data[0]!=0 && adfBootSum(buf)!=boot->checkSum ) {
190 printf("compsum=%lx sum=%lx\n", (long)adfBootSum(buf),(long)boot->checkSum );
191 (*adfEnv.wFct)("adfReadBootBlock : incorrect checksum");
194 return RC_OK;
198 * adfWriteBootBlock
201 * write bootcode ?
203 RETCODE
204 adfWriteBootBlock(struct Volume* vol, struct bBootBlock* boot)
206 unsigned char buf[LOGICAL_BLOCK_SIZE*2];
207 ULONG newSum;
209 boot->dosType[0] = 'D';
210 boot->dosType[1] = 'O';
211 boot->dosType[2] = 'S';
212 boot->dosType[3] = vol->dosType;
214 boot->rootBlock = vol->rootBlock;
216 memcpy(buf, boot, LOGICAL_BLOCK_SIZE*2);
217 #ifdef LITT_ENDIAN
218 swapEndian(buf, SWBL_BOOTBLOCK);
219 #endif
221 if (boot->rootBlock==880 || boot->data[0]!=0) {
222 newSum = adfBootSum(buf);
223 //fprintf(stderr,"sum %x %x\n",newSum,adfBootSum2(buf));
224 swLong(buf+4,newSum);
225 // *(ULONG*)(buf+4) = swapLong((unsigned char*)&newSum);
228 /* dumpBlock(buf);
229 dumpBlock(buf+512);
231 if (adfWriteBlock(vol, 0, buf)!=RC_OK)
232 return RC_ERROR;
233 if (adfWriteBlock(vol, 1, buf+512)!=RC_OK)
234 return RC_ERROR;
235 //puts("adfWriteBootBlock");
236 return RC_OK;
241 * NormalSum
243 * buf = where the block is stored
244 * offset = checksum place (in bytes)
245 * bufLen = buffer length (in bytes)
247 ULONG
248 adfNormalSum( UCHAR* buf, int offset, int bufLen )
250 ULONG newsum;
251 int i;
253 newsum=0L;
254 for(i=0; i < (bufLen/4); i++)
255 if ( i != (offset/4) ) /* old chksum */
256 newsum+=Long(buf+i*4);
257 newsum=(-newsum); /* WARNING */
259 return(newsum);
263 * adfBitmapSum
266 ULONG
267 adfBitmapSum(unsigned char *buf)
269 ULONG newSum;
270 int i;
272 newSum = 0L;
273 for(i=1; i<128; i++)
274 newSum-=Long(buf+i*4);
275 return(newSum);
280 * adfBootSum
283 ULONG
284 adfBootSum(unsigned char *buf)
286 ULONG d, newSum;
287 int i;
289 newSum=0L;
290 for(i=0; i<256; i++) {
291 if (i!=1) {
292 d = Long(buf+i*4);
293 if ( (ULONG_MAX-newSum)<d )
294 newSum++;
295 newSum+=d;
298 newSum = ~newSum; /* not */
300 return(newSum);
303 ULONG
304 adfBootSum2(unsigned char *buf)
306 ULONG prevsum, newSum;
307 int i;
309 prevsum = newSum=0L;
310 for(i=0; i<1024/sizeof(ULONG); i++) {
311 if (i!=1) {
312 prevsum = newSum;
313 newSum += Long(buf+i*4);
314 if (newSum < prevsum)
315 newSum++;
318 newSum = ~newSum; /* not */
320 return(newSum);
324 /*#######################################################################################*/