aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu Aleaxander <Aleaxander@gmail.com>2009-05-17 16:43:55 +0800
committerLiu Aleaxander <Aleaxander@gmail.com>2009-05-17 16:43:55 +0800
commitaffba8c09a3ded66b97ebb09d5213edfaf74fb12 (patch)
tree8e89c31b44d55c21aab26688c3791ae3c88c3e3c
parent487239a50776f619e41ce5a2c9f2f9db6038b8f4 (diff)
downloaddevel-affba8c09a3ded66b97ebb09d5213edfaf74fb12.tar.gz
devel-affba8c09a3ded66b97ebb09d5213edfaf74fb12.tar.xz
devel-affba8c09a3ded66b97ebb09d5213edfaf74fb12.zip
finished the skelton
Well, it has just finished with the skelton, means we still get lots of things to do to make it work.
-rw-r--r--ldlinux.c416
1 files changed, 275 insertions, 141 deletions
diff --git a/ldlinux.c b/ldlinux.c
index 73f3ba2..c81d254 100644
--- a/ldlinux.c
+++ b/ldlinux.c
@@ -134,7 +134,7 @@ void close_dir(xxx* yy)
/**
- * getfssec_edx:
+ * __getfssec_edx:
*
* get multiple sectors from a file
*
@@ -143,12 +143,40 @@ void close_dir(xxx* yy)
* 64K boundaries.
*
* @param: buf
- * @param: curr_sector
+ * @param: curr_sector, the sector where to start reading
* @param: sectors
*
*/
-void getfssec_edx(char *buf, __u32 curr_sector, __u32 sectors)
+void __getfssec(char *buf, __u32 curr_sector, __u32 sectors)
{
+ __u32 frag_start , next_sector;
+ __u32 con_sec_cnt;
+
+ do {
+ /* get fragment */
+ con_sec_cnt = 0;
+ frag_start = curr_sector;
+
+ do {
+ /* get consective sector count */
+ con_sec_cnt ++;
+ sectors --;
+ if ( sectors == 0 )
+ break;
+
+ next_sector = nextsector(curr_sector, &have_more);
+ if ( !have_more )
+ break;
+ }while( next_sector == (++curr_sector) );
+
+
+ /* do read */
+ getlinsecsr(buf, frag_start, con_sec_cnt);
+ buf += con_sec_cnt << 9; /* adjust buffer pointer */
+
+ curr_sector --; /* this is the last sector actually read */
+ curr_sector = next_sector = nextsector(curr_sector, &have_more);
+ }while( sectors );
}
@@ -179,8 +207,7 @@ void getfssec(char *buf, struct open_file_t *file, __u32 sectors)
bytes_read = sectors << SECTOR_SHIFT;
file->file_left -= sectors;
- edx = file_file_sector;
- getfssec_edx(buf, edx, sectors);
+ __getfssec_edx(buf, file->file_sector, sectors);
if ( bytes_read >= file->file_bytesleft ) {
bytes_read = file->file_bytesleft;
@@ -215,63 +242,84 @@ void getfssec(char *buf, struct open_file_t *file, __u32 sectors)
* @param: MangleBuf
*
*/
-void mangle_dos_name(char *MangleBuf, char* filename)
+/**
+ * for now, it can't handle this case:
+ * xyxzxyxjfdkfjdjf.txt as it will just output the first 11 chars
+ * but not care the dot char at the later, so I think we need do
+ * this, but it seems that the SYSLINUX doesn't do it, so I will
+ * make it stay as what it was orignal.
+ *
+ */
+void mangle_dos_name(char *MangleBuf, char *filename)
{
- char *di = MangleBuf;
- char *NameStart = str;
- char al, ah;
- unsigned short ax;
+ char *dst = MangleBuf;
+ char *src = filename;
+ char c;
+ int i = 0;
- int cx = 11; /* # of bytes to write */
- int NameLen;
- loop:
- do {
- al = *str ++;
- if ( al <= ' ' || al == '/')
- goto end;
- if ( al == '.' )
- goto is_period;
-
- if ( al >= 'a' && al <= 'z')
- al -= 32;
+ for (; i < 11; i ++)
+ MangleBuf[i] = ' ';
+
+ for (i = 0; i < 11; i++) {
+ c = *src ++;
+
+ if ( (c <= ' ') || (c == '/') )
+ break;
+
+ if ( c == '.' ) {
+ dst = &MangleBuf[8];
+ i = 7;
+ continue;
+ }
+
+ if (c >= 'a' && c <= 'z')
+ c -= 32;
+ if ( (c == 0xe5) && (i == 11) )
+ c = 0x05;
- ah = cx; /* if the first byte (only!)...*/
- ax = (ah << 8) | al;
- printf("---ax = 0x%x---\n", ax);
- if ( ax == 0x0be5 )
- al = 0x05; /* change it to 05 hex */
- *di ++ = al;
+ *dst++ = c;
+ }
+ MangleBuf[12] = '\0';
+
+ while( (*src != '/') && (*src > ' ') )
+ src ++;
+
+ NameLen = src - filename;
+}
+
+
+
+/**
+ * long_entry_name:
+ *
+ * get the long entry name
+ *
+ */
+char * long_entry_name(dir)
+{
+ id &= 0x3f;
+ while (id ) {
+ if ( !id )
+ goto not_us;
- }while( --cx ); /* don't continue if too long */
+ VFATNext = --id;
+ vfat_cmp:
+ memcpy(unicode_buf, long_name->name1, 5 * 2);
+ memcpy(unicode_buf + 5, long_name->name2, 6 * 2);
+ memcpy(unicode_buf + 11,long_name->name3, 2 * 2);
+ }
- /* find the end for the benefit of longname search */
- do {
- al = *str ++;
- if ( al <= ' ' )
- break;
- }while( al != '/' );
- end:
-
- while( cx -- )
- *di ++ = ' ';
- *di = '\0';
- return ;
+ unicode_to_ascii(entry_name, unicode_buf);
- is_period:
- al = ' ';
- do {
- if (cx <= 3) /* if <= 3 characters left */
- goto loop; /* just ignore it */
- *di ++ = al;
- }while ( --cx );
- *di = '\0';
+ return entry_name;
}
+
/**
* search_dos_dir:
*
@@ -299,67 +347,106 @@ struct open_file_t* search_dos_dir(char *MangleBuf, __u32 dir_sector)
struct fat_dir_entry *dir;
struct fat_long_name_entry *long_dir;
+ __u16 *unicode_buf;
__u32 slots;
file = allocate_file();
if ( !file )
- goto alloc_failure;
-
+ return NULL;
+
+ /*
+ * Compute the value of a possible VFAT longname
+ * "last" entry (which, of coures, comes first ...)
+ */
slots = (NameLen + 12) / 13;
- slots != 0x40;
+ unicode_buf = (__u16 *)malloc(13 * slots);
+ slots |= 0x40;
VFATInit = slots;
VFATNext = slots;
scansector:
- cs = get_cache_block(dir_sector);
- dir = (struct fat_dir_entry *)cs->data;
- entries = SECTOR_SIZE / 32;
-
- scanentry:
- if ( *(char *)dir == 0 )
- goto failure;
- if ( dir->attr != 0x0f )
- goto short_entry;
-
- /* Else it's a long name entry */
- long_dir = (struct fat_long_name_entry *)dir;
- id = long_dir->id;
- if ( id !=VFATNext )
- goto not_us;
-
- if ( id & 0x40 )
- VFATCsum = long_dir->checksum;/*get the initial checksum value*/
- else {
- if ( long_dir->checksum != VFATCsum )
- goto not_us;
- }
-
- done_csum:
- id &= 0x3f;
- if ( !id )
- goto not_us;
-
- VFATNext = --id;
- index = id * 13;
- if ( index >= NameLen )
- goto not_us;
-
- di = NameStart;
- cx = 13;
- vfat_cmp:
do {
- if ( index >= NameLen )
- goto vfat_tail;
+ cs = get_cache_block(dir_sector);
+ dir = (struct fat_dir_entry *)cs->data;
+ entries = SECTOR_SIZE / 32;
+
+ /* scan all the entries in a sector */
+ do {
+ if ( *(char *)dir == 0 )
+ goto failure;
+ if ( dir->attr != 0x0f )
+ goto short_entry;
+
+ /* Else it's a long name entry */
+ long_dir = (struct fat_long_name_entry *)dir;
+ id = long_dir->id;
+ if ( id !=VFATNext )
+ goto not_us;
+
+ if ( id & 0x40 )
+ VFATCsum = long_dir->checksum;/*get the initial checksum value*/
+ else {
+ if ( long_dir->checksum != VFATCsum )
+ goto not_us;
+ }
+
+ id &= 0x3f;
+ slot = --id;
+
+ /* got the long entry name */
+ entry_name = long_entry_name(dir);
+ memcpy(long_name + id * 13, entry_name, 13);
+ if ( id )
+ goto next_entry;
+
+ if ( strcmp(long_name, NameStart) )
+ goto nomatch;
+
+
+ short_entry:
+ if ( dir->attr & 0x08 ) /* ingore volume labels */
+ goto nomacth;
+
+
+ /* If we have a long name match, then VFATNext must be 0 */
+ if ( VFATNext ) {
+ if ( strncmp(MangleBuf, entry_name, 11) == 0 )
+ goto found;
+
+ } else {
+
+ /*
+ * we already have a VFAT long name match, however,
+ * the match is only valid if the checksum matchs.
+ */
+ checksum = get_checksum(dir);
+ if ( checksum = VFATCsum )
+ goto found; /* got a match on long name */
+ }
- }while(--cx);
-
-
+
+ nomatch:
+ VFATNext = VFATInit;
+
+ next_entry:
+ dir ++;
+
+ }while ( --entries );
+
+ dir_sector = nextsector(dir_sector, &have_more);
+ }while ( have_more ); /* scan another secotr */
+ found:
+ file_len = file->file_bytesleft = dir->file_size;
+ first_clust = (dir->first_cluster_high << 16) + dir->first_cluster_low;
+ file->file_sector = (fisrt_clust - 2) << ClustShift + DataArea;
+ attr = dir->attr;
+ return file;
}
@@ -391,50 +478,44 @@ struct open_file_t* searchdir(char *filename, __u32 *file_len)
filename ++;
}
- pathwalk:
- p = filename;
+ while ( *pathname ) {
+ p = filename;
- while ( (*p > ' ') && (*p != '/') )
- p ++;
+ while ( (*p > ' ') && (*p != '/') )
+ p ++;
- //xchg(filename, p);
- if (filename == p)
- goto founddir;
-
- prev_dir = dir_sector;
-
- mangle_dos_name(filename);
- file = search_dos_dir(filename);
- if ( !file )
- goto notfound;
+ //xchg(filename, p);
+ if (filename == p)
+ return;
- if ( *p == '/' )
- goto isdir;
- isfile:
- if ( (attr & 0x18) || (*file_len == 0) )
- goto badfile;
+ prev_dir = dir_sector;
+
+ mangle_dos_name(MangleBuf, filename);
+ file = search_dos_dir(MangleBuf);
+ if ( !file ) {
+ *file_len = 0;
+ return NULL;
+ }
+
+ if ( *p != '/' ) /* we got a file */
+ break;
+
+ if ( attr & 0x10 ) /* subdirectory */
+ return NULL;
+
+ dir_sector = file->file_sector;
+ close(file);
+
+ filename = p + 1; /* search again */
+ }
+ if ( (attr & 0x18) || (*file_len == 0) )
+ return NULL;
+
file->file_bytesleft = *file_len; /**/
file->file_left = ( *file_len + SECTOR_SIZE -1 ) >> SECTOR_SHIFT;
-
- return file;
-
- isdir:
- if ( attr & 0x10 ) /* subdirectory */
- goto badfile;
-
- dir_sector = file->file_sector;
- close(file);
-
- goto pathwalk;
-
- founddir:
- ret;
- badfile:
- *file_len = 0;
- notfound:
- *file_len = 0;
- ret;
+
+ return file;
}
@@ -478,16 +559,37 @@ struct cache_struct *getfatsector(__u32 sector)
* cluster chain. Returns EOF.
*
*/
-void nextsector(__u32 sector)
+void nextsector(__u32 sector, int *have_more)
{
+ __u32 data_sector;
+ __u32 cluster;
+
+ *have_more = 1;
+ if ( sector < DataArea ) {
+ sector ++;
+ if ( sector >= DataArea )
+ *have_more = 0;
+ return sector;
+ }
+
+ data_sector -= DataArea;
+ if ( !data_sector & ClustMask ) /* in a cluster */
+ return (++sector);
+
+ /* got a new cluster */
+ cluster = nextcluster( (data_sector >> ClustShift) + 2 );
+ if ( !cluster ) {
+ *have_more = 0;
+ return 0;
+ }
-
-
-
-}
+ /* return the start of the new cluster */
+ sector = ( (cluster - 2) << ClustShift ) + DataArea;
+ return sector;
+ }
@@ -503,14 +605,44 @@ void nextsector(__u32 sector)
*/
void nextcluster(__u32 clust_num)
{
+ __u32 nextcluster;
+ __u32 fat_sector;
+ struct cache_struct *cs;
+ switch(FATType) {
+ case FAT12:
+ fat_sector = (clust_num + clust_num / 2) >> SECTOR_SHIFT;
+ cs = getfatsector(fat_sector);
+ nextcluster = ((__u16 *)cs->data)[clust_num];
+ if ( clust_num & 0x0001 )
+ nextcluster >>= 4; /* cluster number is ODD */
+ else
+ nextcluster &= 0x0fff; /* cluster number is EVEN */
+ if ( nextcluster > 0x0ff0 )
+ goto fail;
+ break;
+
+ case FAT16:
+ fat_sector = clust_num >> (SECTOR_SHIFT - 2);
+ cs = getfatsector(fat_sector);
+ nextcluster = ((__u16 *)cs->data)[clust_num];
+ if ( next > 0xfff0 )
+ goto fail;
+ break;
+
+ case FAT32:
+ fat_sector = clust_num >> (SECTOR_SHIFT - 2);
+ cs = getfatsector(fat_sector);
+ nextcluster = ((__u32 *)cs->data)[clust_num] & 0x0fffffff;
+ if ( nextcluster > 0x0ffffff0 )
+ goto fail;
+ break;
+ }
- nextcluster_fat12:
-
- nextcluster_fat16:
-
- nextcluster_fat28:
+ return nextcluster;
+ fail: /* got an unexcepted cluster number, so return ZERO */
+ return 0;
}
@@ -539,5 +671,7 @@ void init_fs()
ClustMask = fat.bxSecPerClust - 1;
ClustSize = fat.bxSecPerClust << SECTOR_SIZE;
+ blk_size = SECTOR_SIZE;
+
}