Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
dadigang
Ventoy
Commits
4bf43ab9
Commit
4bf43ab9
authored
Dec 01, 2021
by
longpanda
Browse files
VentoyPlugson ---- A GUI ventoy.json configurator
parent
9eeb94e8
Changes
136
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
5845 additions
and
0 deletions
+5845
-0
Plugson/src/Core/ventoy_util.c
Plugson/src/Core/ventoy_util.c
+255
-0
Plugson/src/Core/ventoy_util.h
Plugson/src/Core/ventoy_util.h
+210
-0
Plugson/src/Core/ventoy_util_linux.c
Plugson/src/Core/ventoy_util_linux.c
+344
-0
Plugson/src/Core/ventoy_util_windows.c
Plugson/src/Core/ventoy_util_windows.c
+813
-0
Plugson/src/Lib/fat_io_lib/API.txt
Plugson/src/Lib/fat_io_lib/API.txt
+22
-0
Plugson/src/Lib/fat_io_lib/COPYRIGHT.txt
Plugson/src/Lib/fat_io_lib/COPYRIGHT.txt
+345
-0
Plugson/src/Lib/fat_io_lib/Configuration.txt
Plugson/src/Lib/fat_io_lib/Configuration.txt
+53
-0
Plugson/src/Lib/fat_io_lib/History.txt
Plugson/src/Lib/fat_io_lib/History.txt
+24
-0
Plugson/src/Lib/fat_io_lib/License.txt
Plugson/src/Lib/fat_io_lib/License.txt
+10
-0
Plugson/src/Lib/fat_io_lib/Media Access API.txt
Plugson/src/Lib/fat_io_lib/Media Access API.txt
+40
-0
Plugson/src/Lib/fat_io_lib/fat_access.c
Plugson/src/Lib/fat_io_lib/fat_access.c
+907
-0
Plugson/src/Lib/fat_io_lib/fat_access.h
Plugson/src/Lib/fat_io_lib/fat_access.h
+133
-0
Plugson/src/Lib/fat_io_lib/fat_cache.c
Plugson/src/Lib/fat_io_lib/fat_cache.c
+91
-0
Plugson/src/Lib/fat_io_lib/fat_cache.h
Plugson/src/Lib/fat_io_lib/fat_cache.h
+13
-0
Plugson/src/Lib/fat_io_lib/fat_defs.h
Plugson/src/Lib/fat_io_lib/fat_defs.h
+128
-0
Plugson/src/Lib/fat_io_lib/fat_filelib.c
Plugson/src/Lib/fat_io_lib/fat_filelib.c
+1603
-0
Plugson/src/Lib/fat_io_lib/fat_filelib.h
Plugson/src/Lib/fat_io_lib/fat_filelib.h
+146
-0
Plugson/src/Lib/fat_io_lib/fat_format.c
Plugson/src/Lib/fat_io_lib/fat_format.c
+532
-0
Plugson/src/Lib/fat_io_lib/fat_format.h
Plugson/src/Lib/fat_io_lib/fat_format.h
+15
-0
Plugson/src/Lib/fat_io_lib/fat_list.h
Plugson/src/Lib/fat_io_lib/fat_list.h
+161
-0
No files found.
Too many changes to show.
To preserve performance only
136 of 136+
files are displayed.
Plain diff
Email patch
Plugson/src/Core/ventoy_util.c
0 → 100644
View file @
4bf43ab9
/******************************************************************************
* ventoy_util.c ---- ventoy util
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <ventoy_define.h>
#include <ventoy_util.h>
static
int
g_tar_filenum
=
0
;
static
char
*
g_tar_buffer
=
NULL
;
static
ventoy_file
*
g_tar_filelist
=
NULL
;
SYSINFO
g_sysinfo
;
unsigned
char
*
g_unxz_buffer
=
NULL
;
int
g_unxz_len
=
0
;
void
unxz_error
(
char
*
x
)
{
vlog
(
"%s
\n
"
,
x
);
}
int
unxz_flush
(
void
*
src
,
unsigned
int
size
)
{
memcpy
(
g_unxz_buffer
+
g_unxz_len
,
src
,
size
);
g_unxz_len
+=
(
int
)
size
;
return
(
int
)
size
;
}
uint64_t
ventoy_get_human_readable_gb
(
uint64_t
SizeBytes
)
{
int
i
;
int
Pow2
=
1
;
double
Delta
;
double
GB
=
SizeBytes
*
1
.
0
/
1000
/
1000
/
1000
;
if
((
SizeBytes
%
SIZE_1GB
)
==
0
)
{
return
(
uint64_t
)(
SizeBytes
/
SIZE_1GB
);
}
for
(
i
=
0
;
i
<
12
;
i
++
)
{
if
(
Pow2
>
GB
)
{
Delta
=
(
Pow2
-
GB
)
/
Pow2
;
}
else
{
Delta
=
(
GB
-
Pow2
)
/
Pow2
;
}
if
(
Delta
<
0
.
05
)
{
return
Pow2
;
}
Pow2
<<=
1
;
}
return
(
uint64_t
)
GB
;
}
int
ventoy_read_file_to_buf
(
const
char
*
FileName
,
int
ExtLen
,
void
**
Bufer
,
int
*
BufLen
)
{
int
FileSize
;
FILE
*
fp
=
NULL
;
void
*
Data
=
NULL
;
#if defined(_MSC_VER) || defined(WIN32)
fopen_s
(
&
fp
,
FileName
,
"rb"
);
#else
fp
=
fopen
(
FileName
,
"rb"
);
#endif
if
(
fp
==
NULL
)
{
vlog
(
"Failed to open file %s"
,
FileName
);
return
1
;
}
fseek
(
fp
,
0
,
SEEK_END
);
FileSize
=
(
int
)
ftell
(
fp
);
Data
=
malloc
(
FileSize
+
ExtLen
);
if
(
!
Data
)
{
fclose
(
fp
);
return
1
;
}
fseek
(
fp
,
0
,
SEEK_SET
);
fread
(
Data
,
1
,
FileSize
,
fp
);
fclose
(
fp
);
*
Bufer
=
Data
;
*
BufLen
=
FileSize
;
return
0
;
}
ventoy_file
*
ventoy_tar_find_file
(
const
char
*
path
)
{
int
i
;
int
len
;
ventoy_file
*
node
=
g_tar_filelist
;
len
=
(
int
)
strlen
(
path
);
for
(
i
=
0
;
i
<
g_tar_filenum
;
i
++
,
node
++
)
{
if
(
node
->
pathlen
==
len
&&
memcmp
(
node
->
path
,
path
,
len
)
==
0
)
{
return
node
;
}
if
(
node
->
pathlen
>
len
)
{
break
;
}
}
return
NULL
;
}
int
ventoy_www_init
(
void
)
{
int
i
=
0
;
int
j
=
0
;
int
size
=
0
;
int
tarsize
=
0
;
int
offset
=
0
;
ventoy_file
*
node
=
NULL
;
ventoy_file
*
node2
=
NULL
;
VENTOY_TAR_HEAD
*
pHead
=
NULL
;
ventoy_file
tmpnode
;
if
(
!
g_tar_filelist
)
{
g_tar_filelist
=
malloc
(
VENTOY_FILE_MAX
*
sizeof
(
ventoy_file
));
g_tar_buffer
=
malloc
(
TAR_BUF_MAX
);
g_tar_filenum
=
0
;
}
if
((
!
g_tar_filelist
)
||
(
!
g_tar_buffer
))
{
return
1
;
}
if
(
ventoy_decompress_tar
(
g_tar_buffer
,
TAR_BUF_MAX
,
&
tarsize
))
{
return
1
;
}
pHead
=
(
VENTOY_TAR_HEAD
*
)
g_tar_buffer
;
node
=
g_tar_filelist
;
while
(
g_tar_filenum
<
VENTOY_FILE_MAX
&&
size
<
tarsize
&&
memcmp
(
pHead
->
magic
,
TMAGIC
,
5
)
==
0
)
{
if
(
pHead
->
typeflag
==
REGTYPE
)
{
node
->
size
=
(
int
)
strtol
(
pHead
->
size
,
NULL
,
8
);
node
->
pathlen
=
(
int
)
scnprintf
(
node
->
path
,
MAX_PATH
,
"%s"
,
pHead
->
name
);
node
->
addr
=
pHead
+
1
;
if
(
node
->
pathlen
==
13
&&
strcmp
(
pHead
->
name
,
"www/buildtime"
)
==
0
)
{
scnprintf
(
g_sysinfo
.
buildtime
,
sizeof
(
g_sysinfo
.
buildtime
),
"%s"
,
(
char
*
)
node
->
addr
);
vlog
(
"Plugson buildtime %s
\n
"
,
g_sysinfo
.
buildtime
);
}
offset
=
512
+
VENTOY_UP_ALIGN
(
node
->
size
,
512
);
node
++
;
g_tar_filenum
++
;
}
else
{
offset
=
512
;
}
pHead
=
(
VENTOY_TAR_HEAD
*
)((
char
*
)
pHead
+
offset
);
size
+=
offset
;
}
//sort
for
(
i
=
0
;
i
<
g_tar_filenum
;
i
++
)
for
(
j
=
i
+
1
;
j
<
g_tar_filenum
;
j
++
)
{
node
=
g_tar_filelist
+
i
;
node2
=
g_tar_filelist
+
j
;
if
(
node
->
pathlen
>
node2
->
pathlen
)
{
memcpy
(
&
tmpnode
,
node
,
sizeof
(
ventoy_file
));
memcpy
(
node
,
node2
,
sizeof
(
ventoy_file
));
memcpy
(
node2
,
&
tmpnode
,
sizeof
(
ventoy_file
));
}
}
vlog
(
"Total extract %d files from tar file.
\n
"
,
g_tar_filenum
);
return
0
;
}
void
ventoy_www_exit
(
void
)
{
check_free
(
g_tar_filelist
);
check_free
(
g_tar_buffer
);
g_tar_filelist
=
NULL
;
g_tar_buffer
=
NULL
;
g_tar_filenum
=
0
;
}
void
ventoy_get_json_path
(
char
*
path
,
char
*
backup
)
{
#if defined(_MSC_VER) || defined(WIN32)
scnprintf
(
path
,
64
,
"%C:
\\
ventoy
\\
ventoy.json"
,
g_cur_dir
[
0
]);
if
(
backup
)
{
scnprintf
(
backup
,
64
,
"%C:
\\
ventoy
\\
ventoy_backup.json"
,
g_cur_dir
[
0
]);
}
#else
scnprintf
(
path
,
64
,
"%s/ventoy/ventoy.json"
,
g_cur_dir
);
if
(
backup
)
{
scnprintf
(
backup
,
64
,
"%s/ventoy/ventoy_backup.json"
,
g_cur_dir
);
}
#endif
}
Plugson/src/Core/ventoy_util.h
0 → 100644
View file @
4bf43ab9
/******************************************************************************
* ventoy_util.h
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __VENTOY_UTIL_H__
#define __VENTOY_UTIL_H__
#define check_free(p) if (p) free(p)
#define vtoy_safe_close_fd(fd) \
{\
if ((fd) >= 0) \
{ \
close(fd); \
(fd) = -1; \
}\
}
extern
char
g_cur_dir
[
MAX_PATH
];
extern
char
g_ventoy_dir
[
MAX_PATH
];
#if defined(_MSC_VER) || defined(WIN32)
typedef
HANDLE
pthread_mutex_t
;
static
__inline
int
pthread_mutex_init
(
pthread_mutex_t
*
mutex
,
void
*
unused
)
{
(
void
)
unused
;
*
mutex
=
CreateMutex
(
NULL
,
FALSE
,
NULL
);
return
*
mutex
==
NULL
?
-
1
:
0
;
}
static
__inline
int
pthread_mutex_destroy
(
pthread_mutex_t
*
mutex
)
{
return
CloseHandle
(
*
mutex
)
==
0
?
-
1
:
0
;
}
static
__inline
int
pthread_mutex_unlock
(
pthread_mutex_t
*
mutex
)
{
return
ReleaseMutex
(
*
mutex
)
==
0
?
-
1
:
0
;
}
static
__inline
int
pthread_mutex_lock
(
pthread_mutex_t
*
mutex
)
{
return
WaitForSingleObject
(
*
mutex
,
INFINITE
)
==
WAIT_OBJECT_0
?
0
:
-
1
;
}
int
ventoy_path_case
(
char
*
path
,
int
slash
);
#else
int
ventoy_get_sys_file_line
(
char
*
buffer
,
int
buflen
,
const
char
*
fmt
,
...);
#define UINT8 uint8_t
#define UINT16 uint16_t
#define UINT32 uint32_t
#define UINT64 uint64_t
static
inline
int
ventoy_path_case
(
char
*
path
,
int
slash
)
{
(
void
)
path
;
(
void
)
slash
;
return
0
;
}
#endif
#define LANGUAGE_EN 0
#define LANGUAGE_CN 1
typedef
struct
SYSINFO
{
char
buildtime
[
128
];
int
syntax_error
;
int
language
;
int
pathcase
;
char
cur_fsname
[
64
];
char
cur_capacity
[
64
];
char
cur_model
[
256
];
char
cur_ventoy_ver
[
64
];
int
cur_secureboot
;
int
cur_part_style
;
char
ip
[
32
];
char
port
[
16
];
}
SYSINFO
;
extern
SYSINFO
g_sysinfo
;
#define TMAGIC "ustar"
#define REGTYPE '0'
#define AREGTYPE '\0'
#define LNKTYPE '1'
#define CHRTYPE '3'
#define BLKTYPE '4'
#define DIRTYPE '5'
#define FIFOTYPE '6'
#define CONTTYPE '7'
#pragma pack(1)
typedef
struct
tag_tar_head
{
char
name
[
100
];
char
mode
[
8
];
char
uid
[
8
];
char
gid
[
8
];
char
size
[
12
];
char
mtime
[
12
];
char
chksum
[
8
];
char
typeflag
;
char
linkname
[
100
];
char
magic
[
6
];
char
version
[
2
];
char
uname
[
32
];
char
gname
[
32
];
char
devmajor
[
8
];
char
devminor
[
8
];
char
prefix
[
155
];
char
padding
[
12
];
}
VENTOY_TAR_HEAD
;
typedef
struct
VENTOY_MAGIC
{
uint32_t
magic1
;
// 0x51 0x52 0x53 0x54
uint32_t
xzlen
;
//
uint32_t
magic2
;
// 0xa1 0xa2 0xa3 0xa4
}
VENTOY_MAGIC
;
#pragma pack()
#define VENTOY_UP_ALIGN(N, align) (((N) + ((align) - 1)) / (align) * (align))
#define VENTOY_FILE_MAX 2048
#if defined(_MSC_VER) || defined(WIN32)
#define million_sleep(a) Sleep(a)
#else
#define million_sleep(a) usleep((a) * 1000)
#endif
typedef
struct
ventoy_file
{
int
size
;
char
path
[
MAX_PATH
];
int
pathlen
;
void
*
addr
;
}
ventoy_file
;
int
ventoy_is_file_exist
(
const
char
*
fmt
,
...);
int
ventoy_is_directory_exist
(
const
char
*
fmt
,
...);
void
ventoy_gen_preudo_uuid
(
void
*
uuid
);
uint64_t
ventoy_get_human_readable_gb
(
uint64_t
SizeBytes
);
void
ventoy_md5
(
const
void
*
data
,
uint32_t
len
,
uint8_t
*
md5
);
int
ventoy_is_disk_mounted
(
const
char
*
devpath
);
int
unxz
(
unsigned
char
*
in
,
int
in_size
,
int
(
*
fill
)(
void
*
dest
,
unsigned
int
size
),
int
(
*
flush
)(
void
*
src
,
unsigned
int
size
),
unsigned
char
*
out
,
int
*
in_used
,
void
(
*
error
)(
char
*
x
));
int
ventoy_read_file_to_buf
(
const
char
*
FileName
,
int
ExtLen
,
void
**
Bufer
,
int
*
BufLen
);
int
ventoy_write_buf_to_file
(
const
char
*
FileName
,
void
*
Bufer
,
int
BufLen
);
const
char
*
ventoy_get_os_language
(
void
);
int
ventoy_get_file_size
(
const
char
*
file
);
int
ventoy_www_init
(
void
);
void
ventoy_www_exit
(
void
);
int
ventoy_decompress_tar
(
char
*
tarbuf
,
int
buflen
,
int
*
tarsize
);
ventoy_file
*
ventoy_tar_find_file
(
const
char
*
path
);
void
ventoy_get_json_path
(
char
*
path
,
char
*
backup
);
int
ventoy_copy_file
(
const
char
*
a
,
const
char
*
b
);
typedef
int
(
*
ventoy_http_writeback_pf
)(
void
);
int
ventoy_start_writeback_thread
(
ventoy_http_writeback_pf
callback
);
void
ventoy_stop_writeback_thread
(
void
);
void
ventoy_set_writeback_event
(
void
);
extern
unsigned
char
*
g_unxz_buffer
;
extern
int
g_unxz_len
;
void
unxz_error
(
char
*
x
);
int
unxz_flush
(
void
*
src
,
unsigned
int
size
);
#endif
/* __VENTOY_UTIL_H__ */
Plugson/src/Core/ventoy_util_linux.c
0 → 100644
View file @
4bf43ab9
/******************************************************************************
* ventoy_util_linux.c ---- ventoy util
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <linux/fs.h>
#include <dirent.h>
#include <time.h>
#include <ventoy_define.h>
#include <ventoy_util.h>
void
ventoy_gen_preudo_uuid
(
void
*
uuid
)
{
int
i
;
int
fd
;
fd
=
open
(
"/dev/urandom"
,
O_RDONLY
|
O_BINARY
);
if
(
fd
<
0
)
{
srand
(
time
(
NULL
));
for
(
i
=
0
;
i
<
8
;
i
++
)
{
*
((
uint16_t
*
)
uuid
+
i
)
=
(
uint16_t
)(
rand
()
&
0xFFFF
);
}
}
else
{
read
(
fd
,
uuid
,
16
);
close
(
fd
);
}
}
int
ventoy_get_sys_file_line
(
char
*
buffer
,
int
buflen
,
const
char
*
fmt
,
...)
{
int
len
;
char
c
;
char
path
[
256
];
va_list
arg
;
va_start
(
arg
,
fmt
);
vsnprintf
(
path
,
256
,
fmt
,
arg
);
va_end
(
arg
);
if
(
access
(
path
,
F_OK
)
>=
0
)
{
FILE
*
fp
=
fopen
(
path
,
"r"
);
memset
(
buffer
,
0
,
buflen
);
len
=
(
int
)
fread
(
buffer
,
1
,
buflen
-
1
,
fp
);
fclose
(
fp
);
while
(
len
>
0
)
{
c
=
buffer
[
len
-
1
];
if
(
c
==
'\r'
||
c
==
'\n'
||
c
==
' '
||
c
==
'\t'
)
{
buffer
[
len
-
1
]
=
0
;
len
--
;
}
else
{
break
;
}
}
return
0
;
}
else
{
vdebug
(
"%s not exist
\n
"
,
path
);
return
1
;
}
}
int
ventoy_is_disk_mounted
(
const
char
*
devpath
)
{
int
len
;
int
mount
=
0
;
char
line
[
512
];
FILE
*
fp
=
NULL
;
fp
=
fopen
(
"/proc/mounts"
,
"r"
);
if
(
!
fp
)
{
return
0
;
}
len
=
(
int
)
strlen
(
devpath
);
while
(
fgets
(
line
,
sizeof
(
line
),
fp
))
{
if
(
strncmp
(
line
,
devpath
,
len
)
==
0
)
{
mount
=
1
;
vdebug
(
"%s mounted <%s>
\n
"
,
devpath
,
line
);
goto
end
;
}
}
end:
fclose
(
fp
);
return
mount
;
}
const
char
*
ventoy_get_os_language
(
void
)
{
const
char
*
env
=
getenv
(
"LANG"
);
if
(
env
&&
strncasecmp
(
env
,
"zh_CN"
,
5
)
==
0
)
{
return
"cn"
;
}
else
{
return
"en"
;
}
}
int
ventoy_is_file_exist
(
const
char
*
fmt
,
...)
{
va_list
ap
;
struct
stat
sb
;
char
fullpath
[
MAX_PATH
];
va_start
(
ap
,
fmt
);
vsnprintf
(
fullpath
,
MAX_PATH
,
fmt
,
ap
);
va_end
(
ap
);
if
(
stat
(
fullpath
,
&
sb
))
{
return
0
;
}
if
(
S_ISREG
(
sb
.
st_mode
))
{
return
1
;
}
return
0
;
}
int
ventoy_is_directory_exist
(
const
char
*
fmt
,
...)
{
va_list
ap
;
struct
stat
sb
;
char
fullpath
[
MAX_PATH
];
va_start
(
ap
,
fmt
);
vsnprintf
(
fullpath
,
MAX_PATH
,
fmt
,
ap
);
va_end
(
ap
);
if
(
stat
(
fullpath
,
&
sb
))
{
return
0
;
}
if
(
S_ISDIR
(
sb
.
st_mode
))
{
return
1
;
}
return
0
;
}
int
ventoy_get_file_size
(
const
char
*
file
)
{
int
Size
=
-
1
;
struct
stat
stStat
;
if
(
stat
(
file
,
&
stStat
)
>=
0
)
{
Size
=
(
int
)(
stStat
.
st_size
);
}
return
Size
;
}
int
ventoy_write_buf_to_file
(
const
char
*
FileName
,
void
*
Bufer
,
int
BufLen
)
{
int
fd
;
int
rc
;
ssize_t
size
;
fd
=
open
(
FileName
,
O_CREAT
|
O_RDWR
|
O_TRUNC
,
0755
);
if
(
fd
<
0
)
{
vlog
(
"Failed to open file %s %d
\n
"
,
FileName
,
errno
);
return
1
;
}
rc
=
fchmod
(
fd
,
0755
);
if
(
rc
)
{
vlog
(
"Failed to chmod <%s> %d
\n
"
,
FileName
,
errno
);
}
size
=
write
(
fd
,
Bufer
,
BufLen
);
if
((
int
)
size
!=
BufLen
)
{
close
(
fd
);
vlog
(
"write file %s failed %d err:%d
\n
"
,
FileName
,
(
int
)
size
,
errno
);
return
1
;
}
fsync
(
fd
);
close
(
fd
);
return
0
;
}
int
ventoy_decompress_tar
(
char
*
tarbuf
,
int
buflen
,
int
*
tarsize
)
{
int
rc
=
1
;
int
inused
=
0
;
int
BufLen
=
0
;
unsigned
char
*
buffer
=
NULL
;
char
tarxz
[
MAX_PATH
];
scnprintf
(
tarxz
,
sizeof
(
tarxz
),
"%s/tool/plugson.tar.xz"
,
g_ventoy_dir
);
if
(
ventoy_read_file_to_buf
(
tarxz
,
0
,
(
void
**
)
&
buffer
,
&
BufLen
))
{
vlog
(
"Failed to read file <%s>
\n
"
,
tarxz
);
return
1
;
}
g_unxz_buffer
=
(
unsigned
char
*
)
tarbuf
;
g_unxz_len
=
0
;
unxz
(
buffer
,
BufLen
,
NULL
,
unxz_flush
,
NULL
,
&
inused
,
unxz_error
);
vlog
(
"xzlen:%u rawdata size:%d
\n
"
,
BufLen
,
g_unxz_len
);
if
(
inused
!=
BufLen
)
{
vlog
(
"Failed to unxz data %d %d
\n
"
,
inused
,
BufLen
);
rc
=
1
;
}
else
{
*
tarsize
=
g_unxz_len
;
rc
=
0
;
}
free
(
buffer
);
return
rc
;
}
static
volatile
int
g_thread_stop
=
0
;
static
pthread_t
g_writeback_thread
;
static
pthread_mutex_t
g_writeback_mutex
;
static
pthread_cond_t
g_writeback_cond
;
static
void
*
ventoy_local_thread_run
(
void
*
data
)
{
ventoy_http_writeback_pf
callback
=
(
ventoy_http_writeback_pf
)
data
;
while
(
1
)
{
pthread_mutex_lock
(
&
g_writeback_mutex
);
pthread_cond_wait
(
&
g_writeback_cond
,
&
g_writeback_mutex
);
if
(
g_thread_stop
)
{
pthread_mutex_unlock
(
&
g_writeback_mutex
);
break
;
}
else
{
callback
();
pthread_mutex_unlock
(
&
g_writeback_mutex
);
}
}
return
NULL
;
}
void
ventoy_set_writeback_event
(
void
)
{
pthread_cond_signal
(
&
g_writeback_cond
);
}
int
ventoy_start_writeback_thread
(
ventoy_http_writeback_pf
callback
)
{
g_thread_stop
=
0
;
pthread_mutex_init
(
&
g_writeback_mutex
,
NULL
);
pthread_cond_init
(
&
g_writeback_cond
,
NULL
);
pthread_create
(
&
g_writeback_thread
,
NULL
,
ventoy_local_thread_run
,
callback
);
return
0
;
}
void
ventoy_stop_writeback_thread
(
void
)
{
g_thread_stop
=
1
;
pthread_cond_signal
(
&
g_writeback_cond
);
pthread_join
(
g_writeback_thread
,
NULL
);
pthread_cond_destroy
(
&
g_writeback_cond
);
pthread_mutex_destroy
(
&
g_writeback_mutex
);
}
int
ventoy_copy_file
(
const
char
*
a
,
const
char
*
b
)
{
int
len
=
0
;
char
*
buf
=
NULL
;
if
(
0
==
ventoy_read_file_to_buf
(
a
,
0
,
(
void
**
)
&
buf
,
&
len
))
{
ventoy_write_buf_to_file
(
b
,
buf
,
len
);
free
(
buf
);
}
return
0
;
}
Plugson/src/Core/ventoy_util_windows.c
0 → 100644
View file @
4bf43ab9
/******************************************************************************
* ventoy_util.c ---- ventoy util
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <ventoy_define.h>
#include <ventoy_util.h>
#include <ventoy_disk.h>
#include "fat_filelib.h"
static
void
TrimString
(
CHAR
*
String
)
{
CHAR
*
Pos1
=
String
;
CHAR
*
Pos2
=
String
;
size_t
Len
=
strlen
(
String
);
while
(
Len
>
0
)
{
if
(
String
[
Len
-
1
]
!=
' '
&&
String
[
Len
-
1
]
!=
'\t'
)
{
break
;
}
String
[
Len
-
1
]
=
0
;
Len
--
;
}
while
(
*
Pos1
==
' '
||
*
Pos1
==
'\t'
)
{
Pos1
++
;
}
while
(
*
Pos1
)
{
*
Pos2
++
=
*
Pos1
++
;
}
*
Pos2
++
=
0
;
return
;
}
void
ventoy_gen_preudo_uuid
(
void
*
uuid
)
{
CoCreateGuid
((
GUID
*
)
uuid
);
}
static
int
IsUTF8Encode
(
const
char
*
src
)
{
int
i
;
const
UCHAR
*
Byte
=
(
const
UCHAR
*
)
src
;
for
(
i
=
0
;
i
<
MAX_PATH
&&
Byte
[
i
];
i
++
)
{
if
(
Byte
[
i
]
>
127
)
{
return
1
;
}
}
return
0
;
}
static
int
Utf8ToUtf16
(
const
char
*
src
,
WCHAR
*
dst
)
{
return
MultiByteToWideChar
(
CP_UTF8
,
0
,
src
,
-
1
,
dst
,
MAX_PATH
*
sizeof
(
WCHAR
));
}
static
int
Utf16ToUtf8
(
const
WCHAR
*
src
,
CHAR
*
dst
)
{
int
size
=
WideCharToMultiByte
(
CP_UTF8
,
0
,
src
,
-
1
,
dst
,
MAX_PATH
,
NULL
,
0
);
dst
[
size
]
=
0
;
return
size
;
}
int
ventoy_path_case
(
char
*
path
,
int
slash
)
{
int
i
;
int
j
=
0
;
int
count
=
0
;
int
isUTF8
=
0
;
BOOL
bRet
;
HANDLE
handle
=
INVALID_HANDLE_VALUE
;
WCHAR
Buffer
[
MAX_PATH
+
16
];
WCHAR
FilePathW
[
MAX_PATH
];
CHAR
FilePathA
[
MAX_PATH
];
FILE_NAME_INFO
*
pInfo
=
NULL
;
if
(
g_sysinfo
.
pathcase
==
0
)
{
return
0
;
}
if
(
path
==
NULL
||
path
[
0
]
==
'/'
||
path
[
0
]
==
'\\'
)
{
return
0
;
}
isUTF8
=
IsUTF8Encode
(
path
);
if
(
isUTF8
)
{
Utf8ToUtf16
(
path
,
FilePathW
);
handle
=
CreateFileW
(
FilePathW
,
GENERIC_READ
,
FILE_SHARE_READ
,
0
,
OPEN_EXISTING
,
FILE_FLAG_BACKUP_SEMANTICS
,
0
);
}
else
{
handle
=
CreateFileA
(
path
,
GENERIC_READ
,
FILE_SHARE_READ
,
0
,
OPEN_EXISTING
,
FILE_FLAG_BACKUP_SEMANTICS
,
0
);
}
if
(
handle
!=
INVALID_HANDLE_VALUE
)
{
bRet
=
GetFileInformationByHandleEx
(
handle
,
FileNameInfo
,
Buffer
,
sizeof
(
Buffer
));
if
(
bRet
)
{
pInfo
=
(
FILE_NAME_INFO
*
)
Buffer
;
if
(
slash
)
{
for
(
i
=
0
;
i
<
(
int
)(
pInfo
->
FileNameLength
/
sizeof
(
WCHAR
));
i
++
)
{
if
(
pInfo
->
FileName
[
i
]
==
L'\\'
)
{
pInfo
->
FileName
[
i
]
=
L'/'
;
}
}
}
pInfo
->
FileName
[(
pInfo
->
FileNameLength
/
sizeof
(
WCHAR
))]
=
0
;
memset
(
FilePathA
,
0
,
sizeof
(
FilePathA
));
Utf16ToUtf8
(
pInfo
->
FileName
,
FilePathA
);
if
(
FilePathA
[
1
]
==
':'
)
{
j
=
3
;
}
else
{
j
=
1
;
}
for
(
i
=
0
;
i
<
MAX_PATH
&&
j
<
MAX_PATH
;
i
++
,
j
++
)
{
if
(
FilePathA
[
j
]
==
0
)
{
break
;
}
if
(
path
[
i
]
!=
FilePathA
[
j
])
{
path
[
i
]
=
FilePathA
[
j
];
count
++
;
}
}
}
CHECK_CLOSE_HANDLE
(
handle
);
}
return
count
;
}
int
ventoy_is_directory_exist
(
const
char
*
Fmt
,
...)
{
va_list
Arg
;
DWORD
Attr
;
int
UTF8
=
0
;
CHAR
FilePathA
[
MAX_PATH
];
WCHAR
FilePathW
[
MAX_PATH
];
va_start
(
Arg
,
Fmt
);
vsnprintf_s
(
FilePathA
,
sizeof
(
FilePathA
),
sizeof
(
FilePathA
),
Fmt
,
Arg
);
va_end
(
Arg
);
UTF8
=
IsUTF8Encode
(
FilePathA
);
if
(
UTF8
)
{
Utf8ToUtf16
(
FilePathA
,
FilePathW
);
Attr
=
GetFileAttributesW
(
FilePathW
);
}
else
{
Attr
=
GetFileAttributesA
(
FilePathA
);
}
if
(
Attr
!=
INVALID_FILE_ATTRIBUTES
&&
(
Attr
&
FILE_ATTRIBUTE_DIRECTORY
))
{
return
TRUE
;
}
return
FALSE
;
}
int
ventoy_is_file_exist
(
const
char
*
Fmt
,
...)
{
va_list
Arg
;
HANDLE
hFile
;
DWORD
Attr
;
int
UTF8
=
0
;
CHAR
FilePathA
[
MAX_PATH
];
WCHAR
FilePathW
[
MAX_PATH
];
va_start
(
Arg
,
Fmt
);
vsnprintf_s
(
FilePathA
,
sizeof
(
FilePathA
),
sizeof
(
FilePathA
),
Fmt
,
Arg
);
va_end
(
Arg
);
UTF8
=
IsUTF8Encode
(
FilePathA
);
if
(
UTF8
)
{
Utf8ToUtf16
(
FilePathA
,
FilePathW
);
hFile
=
CreateFileW
(
FilePathW
,
FILE_READ_EA
,
FILE_SHARE_READ
,
0
,
OPEN_EXISTING
,
0
,
0
);
Attr
=
GetFileAttributesW
(
FilePathW
);
}
else
{
hFile
=
CreateFileA
(
FilePathA
,
FILE_READ_EA
,
FILE_SHARE_READ
,
0
,
OPEN_EXISTING
,
0
,
0
);
Attr
=
GetFileAttributesA
(
FilePathA
);
}
if
(
INVALID_HANDLE_VALUE
==
hFile
)
{
return
0
;
}
CloseHandle
(
hFile
);
if
(
Attr
&
FILE_ATTRIBUTE_DIRECTORY
)
{
return
0
;
}
return
1
;
}
const
char
*
ventoy_get_os_language
(
void
)
{
if
(
GetUserDefaultUILanguage
()
==
0x0804
)
{
return
"cn"
;
}
else
{
return
"en"
;
}
}
int
GetPhyDriveByLogicalDrive
(
int
DriveLetter
,
UINT64
*
Offset
)
{
BOOL
Ret
;
DWORD
dwSize
;
HANDLE
Handle
;
VOLUME_DISK_EXTENTS
DiskExtents
;
CHAR
PhyPath
[
128
];
scnprintf
(
PhyPath
,
sizeof
(
PhyPath
),
"
\\\\
.
\\
%C:"
,
(
CHAR
)
DriveLetter
);
Handle
=
CreateFileA
(
PhyPath
,
0
,
0
,
0
,
OPEN_EXISTING
,
0
,
0
);
if
(
Handle
==
INVALID_HANDLE_VALUE
)
{
vlog
(
"CreateFileA %s failed %u
\n
"
,
PhyPath
,
LASTERR
);
return
-
1
;
}
Ret
=
DeviceIoControl
(
Handle
,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
NULL
,
0
,
&
DiskExtents
,
(
DWORD
)(
sizeof
(
DiskExtents
)),
(
LPDWORD
)
&
dwSize
,
NULL
);
if
(
!
Ret
||
DiskExtents
.
NumberOfDiskExtents
==
0
)
{
vlog
(
"IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTSfailed %u
\n
"
,
LASTERR
);
CHECK_CLOSE_HANDLE
(
Handle
);
return
-
1
;
}
CHECK_CLOSE_HANDLE
(
Handle
);
if
(
Offset
)
{
*
Offset
=
(
UINT64
)(
DiskExtents
.
Extents
[
0
].
StartingOffset
.
QuadPart
);
}
return
(
int
)
DiskExtents
.
Extents
[
0
].
DiskNumber
;
}
int
GetPhyDriveInfo
(
int
PhyDrive
,
UINT64
*
Size
,
CHAR
*
Vendor
,
CHAR
*
Product
)
{
int
ret
=
1
;
BOOL
bRet
;
DWORD
dwBytes
;
CHAR
Drive
[
64
];
HANDLE
Handle
=
INVALID_HANDLE_VALUE
;
GET_LENGTH_INFORMATION
LengthInfo
;
STORAGE_PROPERTY_QUERY
Query
;
STORAGE_DESCRIPTOR_HEADER
DevDescHeader
;
STORAGE_DEVICE_DESCRIPTOR
*
pDevDesc
=
NULL
;
sprintf_s
(
Drive
,
sizeof
(
Drive
),
"
\\\\
.
\\
PhysicalDrive%d"
,
PhyDrive
);
Handle
=
CreateFileA
(
Drive
,
GENERIC_READ
,
FILE_SHARE_READ
,
NULL
,
OPEN_EXISTING
,
0
,
NULL
);
if
(
Handle
==
INVALID_HANDLE_VALUE
)
{
vlog
(
"CreateFileA %s failed %u
\n
"
,
Drive
,
LASTERR
);
goto
out
;
}
bRet
=
DeviceIoControl
(
Handle
,
IOCTL_DISK_GET_LENGTH_INFO
,
NULL
,
0
,
&
LengthInfo
,
sizeof
(
LengthInfo
),
&
dwBytes
,
NULL
);
if
(
!
bRet
)
{
vlog
(
"IOCTL_DISK_GET_LENGTH_INFO failed %u
\n
"
,
LASTERR
);
return
1
;
}
if
(
Size
)
{
*
Size
=
(
UINT64
)
LengthInfo
.
Length
.
QuadPart
;
}
Query
.
PropertyId
=
StorageDeviceProperty
;
Query
.
QueryType
=
PropertyStandardQuery
;
bRet
=
DeviceIoControl
(
Handle
,
IOCTL_STORAGE_QUERY_PROPERTY
,
&
Query
,
sizeof
(
Query
),
&
DevDescHeader
,
sizeof
(
STORAGE_DESCRIPTOR_HEADER
),
&
dwBytes
,
NULL
);
if
(
!
bRet
)
{
vlog
(
"IOCTL_STORAGE_QUERY_PROPERTY failed %u
\n
"
,
LASTERR
);
goto
out
;
}
if
(
DevDescHeader
.
Size
<
sizeof
(
STORAGE_DEVICE_DESCRIPTOR
))
{
vlog
(
"DevDescHeader.size invalid %u
\n
"
,
DevDescHeader
.
Size
);
goto
out
;
}
pDevDesc
=
(
STORAGE_DEVICE_DESCRIPTOR
*
)
malloc
(
DevDescHeader
.
Size
);
if
(
!
pDevDesc
)
{
vlog
(
"malloc failed
\n
"
);
goto
out
;
}
bRet
=
DeviceIoControl
(
Handle
,
IOCTL_STORAGE_QUERY_PROPERTY
,
&
Query
,
sizeof
(
Query
),
pDevDesc
,
DevDescHeader
.
Size
,
&
dwBytes
,
NULL
);
if
(
!
bRet
)
{
vlog
(
"IOCTL_STORAGE_QUERY_PROPERTY failed %u
\n
"
,
LASTERR
);
goto
out
;
}
if
(
pDevDesc
->
VendorIdOffset
&&
Vendor
)
{
strcpy_s
(
Vendor
,
128
,
(
char
*
)
pDevDesc
+
pDevDesc
->
VendorIdOffset
);
TrimString
(
Vendor
);
}
if
(
pDevDesc
->
ProductIdOffset
&&
Product
)
{
strcpy_s
(
Product
,
128
,
(
char
*
)
pDevDesc
+
pDevDesc
->
ProductIdOffset
);
TrimString
(
Product
);
}
ret
=
0
;
out:
CHECK_FREE
(
pDevDesc
);
CHECK_CLOSE_HANDLE
(
Handle
);
return
ret
;
}
int
ventoy_get_file_size
(
const
char
*
file
)
{
int
Size
=
-
1
;
HANDLE
hFile
;
hFile
=
CreateFileA
(
file
,
0
,
0
,
NULL
,
OPEN_EXISTING
,
0
,
NULL
);
if
(
hFile
!=
INVALID_HANDLE_VALUE
)
{
Size
=
(
int
)
GetFileSize
(
hFile
,
NULL
);
CHECK_CLOSE_HANDLE
(
hFile
);
}
return
Size
;
}
static
HANDLE
g_FatPhyDrive
;
static
UINT64
g_Part2StartSec
;
const
CHAR
*
ParseVentoyVersionFromString
(
CHAR
*
Buf
)
{
CHAR
*
Pos
=
NULL
;
CHAR
*
End
=
NULL
;
static
CHAR
LocalVersion
[
64
]
=
{
0
};
Pos
=
strstr
(
Buf
,
"VENTOY_VERSION="
);
if
(
Pos
)
{
Pos
+=
strlen
(
"VENTOY_VERSION="
);
if
(
*
Pos
==
'"'
)
{
Pos
++
;
}
End
=
Pos
;
while
(
*
End
!=
0
&&
*
End
!=
'"'
&&
*
End
!=
'\r'
&&
*
End
!=
'\n'
)
{
End
++
;
}
*
End
=
0
;
sprintf_s
(
LocalVersion
,
sizeof
(
LocalVersion
),
"%s"
,
Pos
);
return
LocalVersion
;
}
return
""
;
}
static
int
GetVentoyVersionFromFatFile
(
CHAR
*
VerBuf
,
size_t
BufLen
)
{
int
rc
=
1
;
int
size
=
0
;
char
*
buf
=
NULL
;
void
*
flfile
=
NULL
;
flfile
=
fl_fopen
(
"/grub/grub.cfg"
,
"rb"
);
if
(
flfile
)
{
fl_fseek
(
flfile
,
0
,
SEEK_END
);
size
=
(
int
)
fl_ftell
(
flfile
);
fl_fseek
(
flfile
,
0
,
SEEK_SET
);
buf
=
(
char
*
)
malloc
(
size
+
1
);
if
(
buf
)
{
fl_fread
(
buf
,
1
,
size
,
flfile
);
buf
[
size
]
=
0
;
rc
=
0
;
sprintf_s
(
VerBuf
,
BufLen
,
"%s"
,
ParseVentoyVersionFromString
(
buf
));
free
(
buf
);
}
fl_fclose
(
flfile
);
}
return
rc
;
}
static
int
VentoyFatDiskRead
(
uint32
Sector
,
uint8
*
Buffer
,
uint32
SectorCount
)
{
DWORD
dwSize
;
BOOL
bRet
;
DWORD
ReadSize
;
LARGE_INTEGER
liCurrentPosition
;
liCurrentPosition
.
QuadPart
=
Sector
+
g_Part2StartSec
;
liCurrentPosition
.
QuadPart
*=
512
;
SetFilePointerEx
(
g_FatPhyDrive
,
liCurrentPosition
,
&
liCurrentPosition
,
FILE_BEGIN
);
ReadSize
=
(
DWORD
)(
SectorCount
*
512
);
bRet
=
ReadFile
(
g_FatPhyDrive
,
Buffer
,
ReadSize
,
&
dwSize
,
NULL
);
if
(
bRet
==
FALSE
||
dwSize
!=
ReadSize
)
{
}
return
1
;
}
static
int
GetVentoyVersion
(
int
PhyDrive
,
ventoy_disk
*
disk
)
{
int
ret
=
1
;
BOOL
bRet
;
DWORD
dwBytes
;
UINT64
Part2Offset
;
HANDLE
Handle
=
INVALID_HANDLE_VALUE
;
VTOY_GPT_INFO
*
pGPT
=
NULL
;
CHAR
Drive
[
64
];
void
*
flfile
=
NULL
;
UCHAR
MbrData
[]
=
{
0xEB
,
0x63
,
0x90
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x56
,
0x54
,
0x00
,
0x47
,
0x65
,
0x00
,
0x48
,
0x44
,
0x00
,
0x52
,
0x64
,
0x00
,
0x20
,
0x45
,
0x72
,
0x0D
,
};
sprintf_s
(
Drive
,
sizeof
(
Drive
),
"
\\\\
.
\\
PhysicalDrive%d"
,
PhyDrive
);
Handle
=
CreateFileA
(
Drive
,
GENERIC_READ
,
FILE_SHARE_READ
,
NULL
,
OPEN_EXISTING
,
0
,
NULL
);
if
(
Handle
==
INVALID_HANDLE_VALUE
)
{
vlog
(
"CreateFileA %s failed %u
\n
"
,
Drive
,
LASTERR
);
goto
out
;
}
pGPT
=
zalloc
(
sizeof
(
VTOY_GPT_INFO
));
if
(
!
pGPT
)
{
goto
out
;
}
bRet
=
ReadFile
(
Handle
,
pGPT
,
sizeof
(
VTOY_GPT_INFO
),
&
dwBytes
,
NULL
);
if
(
!
bRet
||
dwBytes
!=
sizeof
(
VTOY_GPT_INFO
))
{
vlog
(
"ReadFile failed %u
\n
"
,
LASTERR
);
goto
out
;
}
if
(
memcmp
(
pGPT
->
MBR
.
BootCode
,
MbrData
,
0x30
)
||
memcmp
(
pGPT
->
MBR
.
BootCode
+
0x190
,
MbrData
+
0x30
,
0x10
))
{
vlog
(
"Invalid MBR Code %u
\n
"
,
LASTERR
);
goto
out
;
}
if
(
pGPT
->
MBR
.
PartTbl
[
0
].
FsFlag
==
0xEE
)
{
if
(
memcmp
(
pGPT
->
Head
.
Signature
,
"EFI PART"
,
8
))
{
vlog
(
"Invalid GPT Signature
\n
"
);
goto
out
;
}
Part2Offset
=
pGPT
->
PartTbl
[
1
].
StartLBA
;
disk
->
cur_part_style
=
1
;
}
else
{
Part2Offset
=
pGPT
->
MBR
.
PartTbl
[
1
].
StartSectorId
;
disk
->
cur_part_style
=
0
;
}
g_FatPhyDrive
=
Handle
;
g_Part2StartSec
=
Part2Offset
;
fl_init
();
if
(
0
==
fl_attach_media
(
VentoyFatDiskRead
,
NULL
))
{
ret
=
GetVentoyVersionFromFatFile
(
disk
->
cur_ventoy_ver
,
sizeof
(
disk
->
cur_ventoy_ver
));
if
(
ret
==
0
)
{
flfile
=
fl_fopen
(
"/EFI/BOOT/grubx64_real.efi"
,
"rb"
);
if
(
flfile
)
{
disk
->
cur_secureboot
=
1
;
fl_fclose
(
flfile
);
}
}
}
fl_shutdown
();
out:
CHECK_FREE
(
pGPT
);
CHECK_CLOSE_HANDLE
(
Handle
);
return
ret
;
}
int
CheckRuntimeEnvironment
(
char
Letter
,
ventoy_disk
*
disk
)
{
int
PhyDrive
;
UINT64
Offset
=
0
;
char
Drive
[
32
];
DWORD
FsFlag
;
CHAR
Vendor
[
128
]
=
{
0
};
CHAR
Product
[
128
]
=
{
0
};
CHAR
FsName
[
MAX_PATH
];
PhyDrive
=
GetPhyDriveByLogicalDrive
(
Letter
,
&
Offset
);
if
(
PhyDrive
<
0
)
{
vlog
(
"GetPhyDriveByLogicalDrive failed %d %llu
\n
"
,
PhyDrive
,
(
ULONGLONG
)
Offset
);
return
1
;
}
if
(
Offset
!=
1048576
)
{
vlog
(
"Partition offset is NOT 1MB. This is NOT ventoy image partition (%llu)
\n
"
,
(
ULONGLONG
)
Offset
);
return
1
;
}
if
(
GetPhyDriveInfo
(
PhyDrive
,
&
Offset
,
Vendor
,
Product
)
!=
0
)
{
vlog
(
"GetPhyDriveInfo failed
\n
"
);
return
1
;
}
sprintf_s
(
disk
->
cur_capacity
,
sizeof
(
disk
->
cur_capacity
),
"%dGB"
,
(
int
)
ventoy_get_human_readable_gb
(
Offset
));
sprintf_s
(
disk
->
cur_model
,
sizeof
(
disk
->
cur_model
),
"%s %s"
,
Vendor
,
Product
);
scnprintf
(
Drive
,
sizeof
(
Drive
),
"%C:
\\
"
,
Letter
);
if
(
0
==
GetVolumeInformationA
(
Drive
,
NULL
,
0
,
NULL
,
NULL
,
&
FsFlag
,
FsName
,
MAX_PATH
))
{
vlog
(
"GetVolumeInformationA failed %u
\n
"
,
LASTERR
);
return
1
;
}
if
(
_stricmp
(
FsName
,
"NTFS"
)
==
0
)
{
disk
->
pathcase
=
1
;
}
strlcpy
(
disk
->
cur_fsname
,
FsName
);
if
(
GetVentoyVersion
(
PhyDrive
,
disk
)
!=
0
)
{
vlog
(
"GetVentoyVersion failed %u
\n
"
,
LASTERR
);
return
1
;
}
return
0
;
}
int
ventoy_write_buf_to_file
(
const
char
*
FileName
,
void
*
Bufer
,
int
BufLen
)
{
BOOL
bRet
;
DWORD
dwBytes
;
HANDLE
hFile
;
hFile
=
CreateFileA
(
FileName
,
GENERIC_READ
|
GENERIC_WRITE
,
0
,
0
,
CREATE_ALWAYS
,
0
,
0
);
if
(
hFile
==
INVALID_HANDLE_VALUE
)
{
vlog
(
"CreateFile %s failed %u
\n
"
,
FileName
,
LASTERR
);
return
1
;
}
bRet
=
WriteFile
(
hFile
,
Bufer
,
(
DWORD
)
BufLen
,
&
dwBytes
,
NULL
);
if
((
!
bRet
)
||
((
DWORD
)
BufLen
!=
dwBytes
))
{
vlog
(
"Failed to write file <%s> %u err:%u"
,
FileName
,
dwBytes
,
LASTERR
);
CloseHandle
(
hFile
);
return
1
;
}
FlushFileBuffers
(
hFile
);
CloseHandle
(
hFile
);
return
0
;
}
int
ventoy_decompress_tar
(
char
*
tarbuf
,
int
buflen
,
int
*
tarsize
)
{
int
rc
=
1
;
int
inused
;
HANDLE
hFile
;
DWORD
dwSize
;
DWORD
dwRead
;
WCHAR
FullPath
[
MAX_PATH
];
BYTE
*
buffer
;
VENTOY_MAGIC
Magic
;
GetModuleFileNameW
(
NULL
,
FullPath
,
MAX_PATH
);
hFile
=
CreateFileW
(
FullPath
,
GENERIC_READ
,
0
,
NULL
,
OPEN_EXISTING
,
0
,
NULL
);
if
(
hFile
==
INVALID_HANDLE_VALUE
)
{
vlog
(
"Failed to open self %u
\n
"
,
LASTERR
);
return
1
;
}
dwSize
=
GetFileSize
(
hFile
,
NULL
);
if
(
dwSize
==
INVALID_FILE_SIZE
)
{
vlog
(
"Invalid self exe size %u
\n
"
,
LASTERR
);
CHECK_CLOSE_HANDLE
(
hFile
);
return
1
;
}
buffer
=
malloc
(
dwSize
);
if
(
!
buffer
)
{
vlog
(
"Failed to malloc %u
\n
"
,
dwSize
);
CHECK_CLOSE_HANDLE
(
hFile
);
return
1
;
}
ReadFile
(
hFile
,
buffer
,
dwSize
,
&
dwRead
,
NULL
);
memcpy
(
&
Magic
,
buffer
+
dwSize
-
sizeof
(
Magic
),
sizeof
(
Magic
));
if
(
Magic
.
magic1
==
0x54535251
&&
Magic
.
magic2
==
0xa4a3a2a1
)
{
g_unxz_buffer
=
(
UCHAR
*
)
tarbuf
;
g_unxz_len
=
0
;
unxz
(
buffer
+
dwSize
-
Magic
.
xzlen
-
sizeof
(
Magic
),
Magic
.
xzlen
,
NULL
,
unxz_flush
,
NULL
,
&
inused
,
unxz_error
);
vlog
(
"bigexe:%u xzlen:%u rawdata size:%d
\n
"
,
dwSize
,
Magic
.
xzlen
,
g_unxz_len
);
if
(
inused
!=
Magic
.
xzlen
)
{
vlog
(
"Failed to unxz www %d
\n
"
,
inused
);
rc
=
1
;
}
else
{
*
tarsize
=
g_unxz_len
;
rc
=
0
;
}
}
else
{
vlog
(
"Invalid magic 0x%x 0x%x
\n
"
,
Magic
.
magic1
,
Magic
.
magic2
);
rc
=
1
;
}
free
(
buffer
);
CHECK_CLOSE_HANDLE
(
hFile
);
return
rc
;
}
static
volatile
int
g_thread_stop
=
0
;
static
HANDLE
g_writeback_thread
;
static
HANDLE
g_writeback_event
;
DWORD
WINAPI
ventoy_local_thread_run
(
LPVOID
lpParameter
)
{
ventoy_http_writeback_pf
callback
=
(
ventoy_http_writeback_pf
)
lpParameter
;
while
(
1
)
{
WaitForSingleObject
(
g_writeback_event
,
INFINITE
);
if
(
g_thread_stop
)
{
break
;
}
else
{
callback
();
}
}
return
0
;
}
void
ventoy_set_writeback_event
(
void
)
{
SetEvent
(
g_writeback_event
);
}
int
ventoy_start_writeback_thread
(
ventoy_http_writeback_pf
callback
)
{
g_thread_stop
=
0
;
g_writeback_event
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
"VTOYWRBK"
);
g_writeback_thread
=
CreateThread
(
NULL
,
0
,
ventoy_local_thread_run
,
callback
,
0
,
NULL
);
return
0
;
}
void
ventoy_stop_writeback_thread
(
void
)
{
g_thread_stop
=
1
;
ventoy_set_writeback_event
();
WaitForSingleObject
(
g_writeback_thread
,
INFINITE
);
CHECK_CLOSE_HANDLE
(
g_writeback_thread
);
CHECK_CLOSE_HANDLE
(
g_writeback_event
);
}
int
ventoy_copy_file
(
const
char
*
a
,
const
char
*
b
)
{
CopyFileA
(
a
,
b
,
FALSE
);
return
0
;
}
Plugson/src/Lib/fat_io_lib/API.txt
0 → 100644
View file @
4bf43ab9
File IO Lib API
-=-=-=-=-=-=-=-=-
void fl_init(void)
Called to initialize FAT IO library.
This should be called prior to any other functions.
void fl_attach_locks(void (*lock)(void), void (*unlock)(void))
[Optional] File system thread safety locking functions.
For thread safe operation, you should provide lock() and unlock() functions.
Note that locking primitive used must support recursive locking, i.e lock() called within an already ‘locked’ region.
int fl_attach_media(fn_diskio_read rd, fn_diskio_write wr)
This function is used to attach system specific disk/media access functions.
This should be done subsequent to calling fl_init() and fl_attach_locks() (if locking required).
void fl_shutdown(void)
Shutdown the FAT IO library. This purges any un-saved data back to disk.
Plugson/src/Lib/fat_io_lib/COPYRIGHT.txt
0 → 100644
View file @
4bf43ab9
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
Plugson/src/Lib/fat_io_lib/Configuration.txt
0 → 100644
View file @
4bf43ab9
File IO Lib Options
-=-=-=-=-=-=-=-=-=-
See defines in fat_opts.h:
FATFS_IS_LITTLE_ENDIAN [1/0]
Which endian is your system? Set to 1 for little endian, 0 for big endian.
FATFS_MAX_LONG_FILENAME [260]
By default, 260 characters (max LFN length). Increase this to support greater path depths.
FATFS_MAX_OPEN_FILES
The more files you wish to have concurrently open, the greater this number should be.
This increases the number of FL_FILE file structures in the library, each of these is around 1K in size (assuming 512 byte sectors).
FAT_BUFFER_SECTORS
Minimum is 1, more increases performance.
This defines how many FAT sectors can be buffered per FAT_BUFFER entry.
FAT_BUFFERS
Minimum is 1, more increases performance.
This defines how many FAT buffer entries are available.
Memory usage is FAT_BUFFERS * FAT_BUFFER_SECTORS * FAT_SECTOR_SIZE
FATFS_INC_WRITE_SUPPORT
Support file write functionality.
FAT_SECTOR_SIZE
Sector size used by buffers. Most likely to be 512 bytes (standard for ATA/IDE).
FAT_PRINTF
A define that allows the File IO library to print to console/stdout.
Provide your own printf function if printf not available.
FAT_CLUSTER_CACHE_ENTRIES
Size of cluster chain cache (can be undefined if not required).
Mem used = FAT_CLUSTER_CACHE_ENTRIES * 4 * 2
Improves access speed considerably.
FATFS_INC_LFN_SUPPORT [1/0]
Enable/Disable support for long filenames.
FATFS_DIR_LIST_SUPPORT [1/0]
Include support for directory listing.
FATFS_INC_TIME_DATE_SUPPORT [1/0]
Use time/date functions provided by time.h to update creation & modification timestamps.
FATFS_INC_FORMAT_SUPPORT
Include support for formatting disks (FAT16 only).
FAT_PRINTF_NOINC_STDIO
Disable use of printf & inclusion of stdio.h
Plugson/src/Lib/fat_io_lib/History.txt
0 → 100644
View file @
4bf43ab9
Revision History
-=-=-=-=-=-=-=-=-
v2.6.11 - Fix compilation with GCC on 64-bit machines
v2.6.10 - Added support for FAT32 format.
V2.6.9 - Added support for time & date handling.
V2.6.8 - Fixed error with FSINFO sector write.
V2.6.7 - Added fgets().
Fixed C warnings, removed dependancy on some string.h functions.
V2.6.6 – Massive read + write performance improvements.
V2.6.5 – Bug fixes for big endian systems.
V2.6.4 – Further bug fixes and performance improvements for write operations.
V2.6.3 – Peformance improvements, FAT16 formatting support. Various bug fixes.
V2.6 - Basic support for FAT16 added (18-04-10).
V2.5 - Code cleaned up. Many bugs fixed. Thread safety functions added.
V2.x - Write support added as well as better stdio like API.
V1.0 - Rewrite of all code to enable multiple files to be opened and provides a
better file API.
Also better string matching, and generally better C code than origonal
version.
V0.1c - Fetch_ID_Max_LBA() function added to retrieve Drive infomation and stoping
the drive reads from addressing a sector that is out of range.
V0.1b - fopen(), fgetc(), fopenDIR() using new software stack for IDE and FAT32
access.
V0.1a - First release (27/12/03); fopen(), fgetc() unbuffered reads.
Plugson/src/Lib/fat_io_lib/License.txt
0 → 100644
View file @
4bf43ab9
FAT File IO Library License
-=-=-=-=-=-=-=-=-=-=-=-=-=-
This versions license: GPL
If you include GPL software in your project, you must release the source code of that project too.
If you would like a version with a more permissive license for use in closed source commercial applications please contact me for details.
Email: admin@ultra-embedded.com
Plugson/src/Lib/fat_io_lib/Media Access API.txt
0 → 100644
View file @
4bf43ab9
Media Access API
-=-=-=-=-=-=-=-=-
int media_read(uint32 sector, uint8 *buffer, uint32 sector_count)
Params:
Sector: 32-bit sector number
Buffer: Target buffer to read n sectors of data into.
Sector_count: Number of sectors to read.
Return:
int, 1 = success, 0 = failure.
Description:
Application/target specific disk/media read function.
Sector number (sectors are usually 512 byte pages) to read.
Media Write API
int media_write(uint32 sector, uint8 *buffer, uint32 sector_count)
Params:
Sector: 32-bit sector number
Buffer: Target buffer to write n sectors of data from.
Sector_count: Number of sectors to write.
Return:
int, 1 = success, 0 = failure.
Description:
Application/target specific disk/media write function.
Sector number (sectors are usually 512 byte pages) to write to.
File IO Library Linkage
Use the following API to attach the media IO functions to the File IO library.
int fl_attach_media(fn_diskio_read rd, fn_diskio_write wr)
Plugson/src/Lib/fat_io_lib/fat_access.c
0 → 100644
View file @
4bf43ab9
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// FAT File IO Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <string.h>
#include "fat_defs.h"
#include "fat_access.h"
#include "fat_table.h"
#include "fat_write.h"
#include "fat_string.h"
#include "fat_misc.h"
//-----------------------------------------------------------------------------
// fatfs_init: Load FAT Parameters
//-----------------------------------------------------------------------------
int
fatfs_init
(
struct
fatfs
*
fs
)
{
uint8
num_of_fats
;
uint16
reserved_sectors
;
uint32
FATSz
;
uint32
root_dir_sectors
;
uint32
total_sectors
;
uint32
data_sectors
;
uint32
count_of_clusters
;
uint8
valid_partition
=
0
;
fs
->
currentsector
.
address
=
FAT32_INVALID_CLUSTER
;
fs
->
currentsector
.
dirty
=
0
;
fs
->
next_free_cluster
=
0
;
// Invalid
fatfs_fat_init
(
fs
);
// Make sure we have a read function (write function is optional)
if
(
!
fs
->
disk_io
.
read_media
)
return
FAT_INIT_MEDIA_ACCESS_ERROR
;
// MBR: Sector 0 on the disk
// NOTE: Some removeable media does not have this.
// Load MBR (LBA 0) into the 512 byte buffer
if
(
!
fs
->
disk_io
.
read_media
(
0
,
fs
->
currentsector
.
sector
,
1
))
return
FAT_INIT_MEDIA_ACCESS_ERROR
;
// Make Sure 0x55 and 0xAA are at end of sector
// (this should be the case regardless of the MBR or boot sector)
if
(
fs
->
currentsector
.
sector
[
SIGNATURE_POSITION
]
!=
0x55
||
fs
->
currentsector
.
sector
[
SIGNATURE_POSITION
+
1
]
!=
0xAA
)
return
FAT_INIT_INVALID_SIGNATURE
;
// Now check again using the access function to prove endian conversion function
if
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
SIGNATURE_POSITION
)
!=
SIGNATURE_VALUE
)
return
FAT_INIT_ENDIAN_ERROR
;
// Verify packed structures
if
(
sizeof
(
struct
fat_dir_entry
)
!=
FAT_DIR_ENTRY_SIZE
)
return
FAT_INIT_STRUCT_PACKING
;
// Check the partition type code
switch
(
fs
->
currentsector
.
sector
[
PARTITION1_TYPECODE_LOCATION
])
{
case
0x0B
:
case
0x06
:
case
0x0C
:
case
0x0E
:
case
0x0F
:
case
0x05
:
valid_partition
=
1
;
break
;
case
0x00
:
valid_partition
=
0
;
break
;
default:
if
(
fs
->
currentsector
.
sector
[
PARTITION1_TYPECODE_LOCATION
]
<=
0x06
)
valid_partition
=
1
;
break
;
}
// Read LBA Begin for the file system
if
(
valid_partition
)
fs
->
lba_begin
=
GET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
PARTITION1_LBA_BEGIN_LOCATION
);
// Else possibly MBR less disk
else
fs
->
lba_begin
=
0
;
// Load Volume 1 table into sector buffer
// (We may already have this in the buffer if MBR less drive!)
if
(
!
fs
->
disk_io
.
read_media
(
fs
->
lba_begin
,
fs
->
currentsector
.
sector
,
1
))
return
FAT_INIT_MEDIA_ACCESS_ERROR
;
// Make sure there are 512 bytes per cluster
if
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
0x0B
)
!=
FAT_SECTOR_SIZE
)
return
FAT_INIT_INVALID_SECTOR_SIZE
;
// Load Parameters of FAT partition
fs
->
sectors_per_cluster
=
fs
->
currentsector
.
sector
[
BPB_SECPERCLUS
];
reserved_sectors
=
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_RSVDSECCNT
);
num_of_fats
=
fs
->
currentsector
.
sector
[
BPB_NUMFATS
];
fs
->
root_entry_count
=
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_ROOTENTCNT
);
if
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FATSZ16
)
!=
0
)
fs
->
fat_sectors
=
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FATSZ16
);
else
fs
->
fat_sectors
=
GET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FAT32_FATSZ32
);
// For FAT32 (which this may be)
fs
->
rootdir_first_cluster
=
GET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FAT32_ROOTCLUS
);
fs
->
fs_info_sector
=
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FAT32_FSINFO
);
// For FAT16 (which this may be), rootdir_first_cluster is actuall rootdir_first_sector
fs
->
rootdir_first_sector
=
reserved_sectors
+
(
num_of_fats
*
fs
->
fat_sectors
);
fs
->
rootdir_sectors
=
((
fs
->
root_entry_count
*
32
)
+
(
FAT_SECTOR_SIZE
-
1
))
/
FAT_SECTOR_SIZE
;
// First FAT LBA address
fs
->
fat_begin_lba
=
fs
->
lba_begin
+
reserved_sectors
;
// The address of the first data cluster on this volume
fs
->
cluster_begin_lba
=
fs
->
fat_begin_lba
+
(
num_of_fats
*
fs
->
fat_sectors
);
if
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
0x1FE
)
!=
0xAA55
)
// This signature should be AA55
return
FAT_INIT_INVALID_SIGNATURE
;
// Calculate the root dir sectors
root_dir_sectors
=
((
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_ROOTENTCNT
)
*
32
)
+
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_BYTSPERSEC
)
-
1
))
/
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_BYTSPERSEC
);
if
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FATSZ16
)
!=
0
)
FATSz
=
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FATSZ16
);
else
FATSz
=
GET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_FAT32_FATSZ32
);
if
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_TOTSEC16
)
!=
0
)
total_sectors
=
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_TOTSEC16
);
else
total_sectors
=
GET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_TOTSEC32
);
data_sectors
=
total_sectors
-
(
GET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
BPB_RSVDSECCNT
)
+
(
fs
->
currentsector
.
sector
[
BPB_NUMFATS
]
*
FATSz
)
+
root_dir_sectors
);
// Find out which version of FAT this is...
if
(
fs
->
sectors_per_cluster
!=
0
)
{
count_of_clusters
=
data_sectors
/
fs
->
sectors_per_cluster
;
if
(
count_of_clusters
<
4085
)
// Volume is FAT12
return
FAT_INIT_WRONG_FILESYS_TYPE
;
else
if
(
count_of_clusters
<
65525
)
{
// Clear this FAT32 specific param
fs
->
rootdir_first_cluster
=
0
;
// Volume is FAT16
fs
->
fat_type
=
FAT_TYPE_16
;
return
FAT_INIT_OK
;
}
else
{
// Volume is FAT32
fs
->
fat_type
=
FAT_TYPE_32
;
return
FAT_INIT_OK
;
}
}
else
return
FAT_INIT_WRONG_FILESYS_TYPE
;
}
//-----------------------------------------------------------------------------
// fatfs_lba_of_cluster: This function converts a cluster number into a sector /
// LBA number.
//-----------------------------------------------------------------------------
uint32
fatfs_lba_of_cluster
(
struct
fatfs
*
fs
,
uint32
Cluster_Number
)
{
if
(
fs
->
fat_type
==
FAT_TYPE_16
)
return
(
fs
->
cluster_begin_lba
+
(
fs
->
root_entry_count
*
32
/
FAT_SECTOR_SIZE
)
+
((
Cluster_Number
-
2
)
*
fs
->
sectors_per_cluster
));
else
return
((
fs
->
cluster_begin_lba
+
((
Cluster_Number
-
2
)
*
fs
->
sectors_per_cluster
)));
}
//-----------------------------------------------------------------------------
// fatfs_sector_read:
//-----------------------------------------------------------------------------
int
fatfs_sector_read
(
struct
fatfs
*
fs
,
uint32
lba
,
uint8
*
target
,
uint32
count
)
{
return
fs
->
disk_io
.
read_media
(
lba
,
target
,
count
);
}
//-----------------------------------------------------------------------------
// fatfs_sector_write:
//-----------------------------------------------------------------------------
int
fatfs_sector_write
(
struct
fatfs
*
fs
,
uint32
lba
,
uint8
*
target
,
uint32
count
)
{
return
fs
->
disk_io
.
write_media
(
lba
,
target
,
count
);
}
//-----------------------------------------------------------------------------
// fatfs_sector_reader: From the provided startcluster and sector offset
// Returns True if success, returns False if not (including if read out of range)
//-----------------------------------------------------------------------------
int
fatfs_sector_reader
(
struct
fatfs
*
fs
,
uint32
start_cluster
,
uint32
offset
,
uint8
*
target
)
{
uint32
sector_to_read
=
0
;
uint32
cluster_to_read
=
0
;
uint32
cluster_chain
=
0
;
uint32
i
;
uint32
lba
;
// FAT16 Root directory
if
(
fs
->
fat_type
==
FAT_TYPE_16
&&
start_cluster
==
0
)
{
if
(
offset
<
fs
->
rootdir_sectors
)
lba
=
fs
->
lba_begin
+
fs
->
rootdir_first_sector
+
offset
;
else
return
0
;
}
// FAT16/32 Other
else
{
// Set start of cluster chain to initial value
cluster_chain
=
start_cluster
;
// Find parameters
cluster_to_read
=
offset
/
fs
->
sectors_per_cluster
;
sector_to_read
=
offset
-
(
cluster_to_read
*
fs
->
sectors_per_cluster
);
// Follow chain to find cluster to read
for
(
i
=
0
;
i
<
cluster_to_read
;
i
++
)
cluster_chain
=
fatfs_find_next_cluster
(
fs
,
cluster_chain
);
// If end of cluster chain then return false
if
(
cluster_chain
==
FAT32_LAST_CLUSTER
)
return
0
;
// Calculate sector address
lba
=
fatfs_lba_of_cluster
(
fs
,
cluster_chain
)
+
sector_to_read
;
}
// User provided target array
if
(
target
)
return
fs
->
disk_io
.
read_media
(
lba
,
target
,
1
);
// Else read sector if not already loaded
else
if
(
lba
!=
fs
->
currentsector
.
address
)
{
fs
->
currentsector
.
address
=
lba
;
return
fs
->
disk_io
.
read_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
);
}
else
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_read_sector: Read from the provided cluster and sector offset
// Returns True if success, returns False if not
//-----------------------------------------------------------------------------
int
fatfs_read_sector
(
struct
fatfs
*
fs
,
uint32
cluster
,
uint32
sector
,
uint8
*
target
)
{
// FAT16 Root directory
if
(
fs
->
fat_type
==
FAT_TYPE_16
&&
cluster
==
0
)
{
uint32
lba
;
// In FAT16, there are a limited amount of sectors in root dir!
if
(
sector
<
fs
->
rootdir_sectors
)
lba
=
fs
->
lba_begin
+
fs
->
rootdir_first_sector
+
sector
;
else
return
0
;
// User target buffer passed in
if
(
target
)
{
// Read from disk
return
fs
->
disk_io
.
read_media
(
lba
,
target
,
1
);
}
else
{
// Calculate read address
fs
->
currentsector
.
address
=
lba
;
// Read from disk
return
fs
->
disk_io
.
read_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
);
}
}
// FAT16/32 Other
else
{
// User target buffer passed in
if
(
target
)
{
// Calculate read address
uint32
lba
=
fatfs_lba_of_cluster
(
fs
,
cluster
)
+
sector
;
// Read from disk
return
fs
->
disk_io
.
read_media
(
lba
,
target
,
1
);
}
else
{
// Calculate write address
fs
->
currentsector
.
address
=
fatfs_lba_of_cluster
(
fs
,
cluster
)
+
sector
;
// Read from disk
return
fs
->
disk_io
.
read_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
);
}
}
}
//-----------------------------------------------------------------------------
// fatfs_write_sector: Write to the provided cluster and sector offset
// Returns True if success, returns False if not
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fatfs_write_sector
(
struct
fatfs
*
fs
,
uint32
cluster
,
uint32
sector
,
uint8
*
target
)
{
// No write access?
if
(
!
fs
->
disk_io
.
write_media
)
return
0
;
// FAT16 Root directory
if
(
fs
->
fat_type
==
FAT_TYPE_16
&&
cluster
==
0
)
{
uint32
lba
;
// In FAT16 we cannot extend the root dir!
if
(
sector
<
fs
->
rootdir_sectors
)
lba
=
fs
->
lba_begin
+
fs
->
rootdir_first_sector
+
sector
;
else
return
0
;
// User target buffer passed in
if
(
target
)
{
// Write to disk
return
fs
->
disk_io
.
write_media
(
lba
,
target
,
1
);
}
else
{
// Calculate write address
fs
->
currentsector
.
address
=
lba
;
// Write to disk
return
fs
->
disk_io
.
write_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
);
}
}
// FAT16/32 Other
else
{
// User target buffer passed in
if
(
target
)
{
// Calculate write address
uint32
lba
=
fatfs_lba_of_cluster
(
fs
,
cluster
)
+
sector
;
// Write to disk
return
fs
->
disk_io
.
write_media
(
lba
,
target
,
1
);
}
else
{
// Calculate write address
fs
->
currentsector
.
address
=
fatfs_lba_of_cluster
(
fs
,
cluster
)
+
sector
;
// Write to disk
return
fs
->
disk_io
.
write_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
);
}
}
}
#endif
//-----------------------------------------------------------------------------
// fatfs_show_details: Show the details about the filesystem
//-----------------------------------------------------------------------------
void
fatfs_show_details
(
struct
fatfs
*
fs
)
{
FAT_PRINTF
((
"FAT details:
\r\n
"
));
FAT_PRINTF
((
" Type =%s"
,
(
fs
->
fat_type
==
FAT_TYPE_32
)
?
"FAT32"
:
"FAT16"
));
FAT_PRINTF
((
" Root Dir First Cluster = %x
\r\n
"
,
fs
->
rootdir_first_cluster
));
FAT_PRINTF
((
" FAT Begin LBA = 0x%x
\r\n
"
,
fs
->
fat_begin_lba
));
FAT_PRINTF
((
" Cluster Begin LBA = 0x%x
\r\n
"
,
fs
->
cluster_begin_lba
));
FAT_PRINTF
((
" Sectors Per Cluster = %d
\r\n
"
,
fs
->
sectors_per_cluster
));
}
//-----------------------------------------------------------------------------
// fatfs_get_root_cluster: Get the root dir cluster
//-----------------------------------------------------------------------------
uint32
fatfs_get_root_cluster
(
struct
fatfs
*
fs
)
{
// NOTE: On FAT16 this will be 0 which has a special meaning...
return
fs
->
rootdir_first_cluster
;
}
//-------------------------------------------------------------
// fatfs_get_file_entry: Find the file entry for a filename
//-------------------------------------------------------------
uint32
fatfs_get_file_entry
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
name_to_find
,
struct
fat_dir_entry
*
sfEntry
)
{
uint8
item
=
0
;
uint16
recordoffset
=
0
;
uint8
i
=
0
;
int
x
=
0
;
char
*
long_filename
=
NULL
;
char
short_filename
[
13
];
struct
lfn_cache
lfn
;
int
dotRequired
=
0
;
struct
fat_dir_entry
*
directoryEntry
;
fatfs_lfn_cache_init
(
&
lfn
,
1
);
// Main cluster following loop
while
(
1
)
{
// Read sector
if
(
fatfs_sector_reader
(
fs
,
Cluster
,
x
++
,
0
))
// If sector read was successfull
{
// Analyse Sector
for
(
item
=
0
;
item
<
FAT_DIR_ENTRIES_PER_SECTOR
;
item
++
)
{
// Create the multiplier for sector access
recordoffset
=
FAT_DIR_ENTRY_SIZE
*
item
;
// Overlay directory entry over buffer
directoryEntry
=
(
struct
fat_dir_entry
*
)(
fs
->
currentsector
.
sector
+
recordoffset
);
#if FATFS_INC_LFN_SUPPORT
// Long File Name Text Found
if
(
fatfs_entry_lfn_text
(
directoryEntry
)
)
fatfs_lfn_cache_entry
(
&
lfn
,
fs
->
currentsector
.
sector
+
recordoffset
);
// If Invalid record found delete any long file name information collated
else
if
(
fatfs_entry_lfn_invalid
(
directoryEntry
)
)
fatfs_lfn_cache_init
(
&
lfn
,
0
);
// Normal SFN Entry and Long text exists
else
if
(
fatfs_entry_lfn_exists
(
&
lfn
,
directoryEntry
)
)
{
long_filename
=
fatfs_lfn_cache_get
(
&
lfn
);
// Compare names to see if they match
if
(
fatfs_compare_names
(
long_filename
,
name_to_find
))
{
memcpy
(
sfEntry
,
directoryEntry
,
sizeof
(
struct
fat_dir_entry
));
return
1
;
}
fatfs_lfn_cache_init
(
&
lfn
,
0
);
}
else
#endif
// Normal Entry, only 8.3 Text
if
(
fatfs_entry_sfn_only
(
directoryEntry
)
)
{
memset
(
short_filename
,
0
,
sizeof
(
short_filename
));
// Copy name to string
for
(
i
=
0
;
i
<
8
;
i
++
)
short_filename
[
i
]
=
directoryEntry
->
Name
[
i
];
// Extension
dotRequired
=
0
;
for
(
i
=
8
;
i
<
11
;
i
++
)
{
short_filename
[
i
+
1
]
=
directoryEntry
->
Name
[
i
];
if
(
directoryEntry
->
Name
[
i
]
!=
' '
)
dotRequired
=
1
;
}
// Dot only required if extension present
if
(
dotRequired
)
{
// If not . or .. entry
if
(
short_filename
[
0
]
!=
'.'
)
short_filename
[
8
]
=
'.'
;
else
short_filename
[
8
]
=
' '
;
}
else
short_filename
[
8
]
=
' '
;
// Compare names to see if they match
if
(
fatfs_compare_names
(
short_filename
,
name_to_find
))
{
memcpy
(
sfEntry
,
directoryEntry
,
sizeof
(
struct
fat_dir_entry
));
return
1
;
}
fatfs_lfn_cache_init
(
&
lfn
,
0
);
}
}
// End of if
}
else
break
;
}
// End of while loop
return
0
;
}
//-------------------------------------------------------------
// fatfs_sfn_exists: Check if a short filename exists.
// NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
//-------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fatfs_sfn_exists
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
shortname
)
{
uint8
item
=
0
;
uint16
recordoffset
=
0
;
int
x
=
0
;
struct
fat_dir_entry
*
directoryEntry
;
// Main cluster following loop
while
(
1
)
{
// Read sector
if
(
fatfs_sector_reader
(
fs
,
Cluster
,
x
++
,
0
))
// If sector read was successfull
{
// Analyse Sector
for
(
item
=
0
;
item
<
FAT_DIR_ENTRIES_PER_SECTOR
;
item
++
)
{
// Create the multiplier for sector access
recordoffset
=
FAT_DIR_ENTRY_SIZE
*
item
;
// Overlay directory entry over buffer
directoryEntry
=
(
struct
fat_dir_entry
*
)(
fs
->
currentsector
.
sector
+
recordoffset
);
#if FATFS_INC_LFN_SUPPORT
// Long File Name Text Found
if
(
fatfs_entry_lfn_text
(
directoryEntry
)
)
;
// If Invalid record found delete any long file name information collated
else
if
(
fatfs_entry_lfn_invalid
(
directoryEntry
)
)
;
else
#endif
// Normal Entry, only 8.3 Text
if
(
fatfs_entry_sfn_only
(
directoryEntry
)
)
{
if
(
strncmp
((
const
char
*
)
directoryEntry
->
Name
,
shortname
,
11
)
==
0
)
return
1
;
}
}
// End of if
}
else
break
;
}
// End of while loop
return
0
;
}
#endif
//-------------------------------------------------------------
// fatfs_update_timestamps: Update date/time details
//-------------------------------------------------------------
#if FATFS_INC_TIME_DATE_SUPPORT
int
fatfs_update_timestamps
(
struct
fat_dir_entry
*
directoryEntry
,
int
create
,
int
modify
,
int
access
)
{
time_t
time_now
;
struct
tm
*
time_info
;
uint16
fat_time
;
uint16
fat_date
;
// Get system time
time
(
&
time_now
);
// Convert to local time
time_info
=
localtime
(
&
time_now
);
// Convert time to FAT format
fat_time
=
fatfs_convert_to_fat_time
(
time_info
->
tm_hour
,
time_info
->
tm_min
,
time_info
->
tm_sec
);
// Convert date to FAT format
fat_date
=
fatfs_convert_to_fat_date
(
time_info
->
tm_mday
,
time_info
->
tm_mon
+
1
,
time_info
->
tm_year
+
1900
);
// Update requested fields
if
(
create
)
{
directoryEntry
->
CrtTime
[
1
]
=
fat_time
>>
8
;
directoryEntry
->
CrtTime
[
0
]
=
fat_time
>>
0
;
directoryEntry
->
CrtDate
[
1
]
=
fat_date
>>
8
;
directoryEntry
->
CrtDate
[
0
]
=
fat_date
>>
0
;
}
if
(
modify
)
{
directoryEntry
->
WrtTime
[
1
]
=
fat_time
>>
8
;
directoryEntry
->
WrtTime
[
0
]
=
fat_time
>>
0
;
directoryEntry
->
WrtDate
[
1
]
=
fat_date
>>
8
;
directoryEntry
->
WrtDate
[
0
]
=
fat_date
>>
0
;
}
if
(
access
)
{
directoryEntry
->
LstAccDate
[
1
]
=
fat_time
>>
8
;
directoryEntry
->
LstAccDate
[
0
]
=
fat_time
>>
0
;
directoryEntry
->
LstAccDate
[
1
]
=
fat_date
>>
8
;
directoryEntry
->
LstAccDate
[
0
]
=
fat_date
>>
0
;
}
return
1
;
}
#endif
//-------------------------------------------------------------
// fatfs_update_file_length: Find a SFN entry and update it
// NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
//-------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fatfs_update_file_length
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
shortname
,
uint32
fileLength
)
{
uint8
item
=
0
;
uint16
recordoffset
=
0
;
int
x
=
0
;
struct
fat_dir_entry
*
directoryEntry
;
// No write access?
if
(
!
fs
->
disk_io
.
write_media
)
return
0
;
// Main cluster following loop
while
(
1
)
{
// Read sector
if
(
fatfs_sector_reader
(
fs
,
Cluster
,
x
++
,
0
))
// If sector read was successfull
{
// Analyse Sector
for
(
item
=
0
;
item
<
FAT_DIR_ENTRIES_PER_SECTOR
;
item
++
)
{
// Create the multiplier for sector access
recordoffset
=
FAT_DIR_ENTRY_SIZE
*
item
;
// Overlay directory entry over buffer
directoryEntry
=
(
struct
fat_dir_entry
*
)(
fs
->
currentsector
.
sector
+
recordoffset
);
#if FATFS_INC_LFN_SUPPORT
// Long File Name Text Found
if
(
fatfs_entry_lfn_text
(
directoryEntry
)
)
;
// If Invalid record found delete any long file name information collated
else
if
(
fatfs_entry_lfn_invalid
(
directoryEntry
)
)
;
// Normal Entry, only 8.3 Text
else
#endif
if
(
fatfs_entry_sfn_only
(
directoryEntry
)
)
{
if
(
strncmp
((
const
char
*
)
directoryEntry
->
Name
,
shortname
,
11
)
==
0
)
{
directoryEntry
->
FileSize
=
FAT_HTONL
(
fileLength
);
#if FATFS_INC_TIME_DATE_SUPPORT
// Update access / modify time & date
fatfs_update_timestamps
(
directoryEntry
,
0
,
1
,
1
);
#endif
// Update sfn entry
memcpy
((
uint8
*
)(
fs
->
currentsector
.
sector
+
recordoffset
),
(
uint8
*
)
directoryEntry
,
sizeof
(
struct
fat_dir_entry
));
// Write sector back
return
fs
->
disk_io
.
write_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
);
}
}
}
// End of if
}
else
break
;
}
// End of while loop
return
0
;
}
#endif
//-------------------------------------------------------------
// fatfs_mark_file_deleted: Find a SFN entry and mark if as deleted
// NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
//-------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fatfs_mark_file_deleted
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
shortname
)
{
uint8
item
=
0
;
uint16
recordoffset
=
0
;
int
x
=
0
;
struct
fat_dir_entry
*
directoryEntry
;
// No write access?
if
(
!
fs
->
disk_io
.
write_media
)
return
0
;
// Main cluster following loop
while
(
1
)
{
// Read sector
if
(
fatfs_sector_reader
(
fs
,
Cluster
,
x
++
,
0
))
// If sector read was successfull
{
// Analyse Sector
for
(
item
=
0
;
item
<
FAT_DIR_ENTRIES_PER_SECTOR
;
item
++
)
{
// Create the multiplier for sector access
recordoffset
=
FAT_DIR_ENTRY_SIZE
*
item
;
// Overlay directory entry over buffer
directoryEntry
=
(
struct
fat_dir_entry
*
)(
fs
->
currentsector
.
sector
+
recordoffset
);
#if FATFS_INC_LFN_SUPPORT
// Long File Name Text Found
if
(
fatfs_entry_lfn_text
(
directoryEntry
)
)
;
// If Invalid record found delete any long file name information collated
else
if
(
fatfs_entry_lfn_invalid
(
directoryEntry
)
)
;
// Normal Entry, only 8.3 Text
else
#endif
if
(
fatfs_entry_sfn_only
(
directoryEntry
)
)
{
if
(
strncmp
((
const
char
*
)
directoryEntry
->
Name
,
shortname
,
11
)
==
0
)
{
// Mark as deleted
directoryEntry
->
Name
[
0
]
=
FILE_HEADER_DELETED
;
#if FATFS_INC_TIME_DATE_SUPPORT
// Update access / modify time & date
fatfs_update_timestamps
(
directoryEntry
,
0
,
1
,
1
);
#endif
// Update sfn entry
memcpy
((
uint8
*
)(
fs
->
currentsector
.
sector
+
recordoffset
),
(
uint8
*
)
directoryEntry
,
sizeof
(
struct
fat_dir_entry
));
// Write sector back
return
fs
->
disk_io
.
write_media
(
fs
->
currentsector
.
address
,
fs
->
currentsector
.
sector
,
1
);
}
}
}
// End of if
}
else
break
;
}
// End of while loop
return
0
;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_list_directory_start: Initialise a directory listing procedure
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
void
fatfs_list_directory_start
(
struct
fatfs
*
fs
,
struct
fs_dir_list_status
*
dirls
,
uint32
StartCluster
)
{
dirls
->
cluster
=
StartCluster
;
dirls
->
sector
=
0
;
dirls
->
offset
=
0
;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_list_directory_next: Get the next entry in the directory.
// Returns: 1 = found, 0 = end of listing
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
int
fatfs_list_directory_next
(
struct
fatfs
*
fs
,
struct
fs_dir_list_status
*
dirls
,
struct
fs_dir_ent
*
entry
)
{
uint8
i
,
item
;
uint16
recordoffset
;
struct
fat_dir_entry
*
directoryEntry
;
char
*
long_filename
=
NULL
;
char
short_filename
[
13
];
struct
lfn_cache
lfn
;
int
dotRequired
=
0
;
int
result
=
0
;
// Initialise LFN cache first
fatfs_lfn_cache_init
(
&
lfn
,
0
);
while
(
1
)
{
// If data read OK
if
(
fatfs_sector_reader
(
fs
,
dirls
->
cluster
,
dirls
->
sector
,
0
))
{
// Maximum of 16 directory entries
for
(
item
=
dirls
->
offset
;
item
<
FAT_DIR_ENTRIES_PER_SECTOR
;
item
++
)
{
// Increase directory offset
recordoffset
=
FAT_DIR_ENTRY_SIZE
*
item
;
// Overlay directory entry over buffer
directoryEntry
=
(
struct
fat_dir_entry
*
)(
fs
->
currentsector
.
sector
+
recordoffset
);
#if FATFS_INC_LFN_SUPPORT
// Long File Name Text Found
if
(
fatfs_entry_lfn_text
(
directoryEntry
)
)
fatfs_lfn_cache_entry
(
&
lfn
,
fs
->
currentsector
.
sector
+
recordoffset
);
// If Invalid record found delete any long file name information collated
else
if
(
fatfs_entry_lfn_invalid
(
directoryEntry
)
)
fatfs_lfn_cache_init
(
&
lfn
,
0
);
// Normal SFN Entry and Long text exists
else
if
(
fatfs_entry_lfn_exists
(
&
lfn
,
directoryEntry
)
)
{
// Get text
long_filename
=
fatfs_lfn_cache_get
(
&
lfn
);
#if defined(_MSC_VER) || defined(WIN32)
strcpy_s
(
entry
->
filename
,
FATFS_MAX_LONG_FILENAME
-
1
,
long_filename
);
#else
strncpy
(
entry
->
filename
,
long_filename
,
FATFS_MAX_LONG_FILENAME
-
1
);
#endif
if
(
fatfs_entry_is_dir
(
directoryEntry
))
entry
->
is_dir
=
1
;
else
entry
->
is_dir
=
0
;
#if FATFS_INC_TIME_DATE_SUPPORT
// Get time / dates
entry
->
create_time
=
((
uint16
)
directoryEntry
->
CrtTime
[
1
]
<<
8
)
|
directoryEntry
->
CrtTime
[
0
];
entry
->
create_date
=
((
uint16
)
directoryEntry
->
CrtDate
[
1
]
<<
8
)
|
directoryEntry
->
CrtDate
[
0
];
entry
->
access_date
=
((
uint16
)
directoryEntry
->
LstAccDate
[
1
]
<<
8
)
|
directoryEntry
->
LstAccDate
[
0
];
entry
->
write_time
=
((
uint16
)
directoryEntry
->
WrtTime
[
1
]
<<
8
)
|
directoryEntry
->
WrtTime
[
0
];
entry
->
write_date
=
((
uint16
)
directoryEntry
->
WrtDate
[
1
]
<<
8
)
|
directoryEntry
->
WrtDate
[
0
];
#endif
entry
->
size
=
FAT_HTONL
(
directoryEntry
->
FileSize
);
entry
->
cluster
=
(
FAT_HTONS
(
directoryEntry
->
FstClusHI
)
<<
16
)
|
FAT_HTONS
(
directoryEntry
->
FstClusLO
);
// Next starting position
dirls
->
offset
=
item
+
1
;
result
=
1
;
return
1
;
}
// Normal Entry, only 8.3 Text
else
#endif
if
(
fatfs_entry_sfn_only
(
directoryEntry
)
)
{
fatfs_lfn_cache_init
(
&
lfn
,
0
);
memset
(
short_filename
,
0
,
sizeof
(
short_filename
));
// Copy name to string
for
(
i
=
0
;
i
<
8
;
i
++
)
short_filename
[
i
]
=
directoryEntry
->
Name
[
i
];
// Extension
dotRequired
=
0
;
for
(
i
=
8
;
i
<
11
;
i
++
)
{
short_filename
[
i
+
1
]
=
directoryEntry
->
Name
[
i
];
if
(
directoryEntry
->
Name
[
i
]
!=
' '
)
dotRequired
=
1
;
}
// Dot only required if extension present
if
(
dotRequired
)
{
// If not . or .. entry
if
(
short_filename
[
0
]
!=
'.'
)
short_filename
[
8
]
=
'.'
;
else
short_filename
[
8
]
=
' '
;
}
else
short_filename
[
8
]
=
' '
;
fatfs_get_sfn_display_name
(
entry
->
filename
,
short_filename
);
if
(
fatfs_entry_is_dir
(
directoryEntry
))
entry
->
is_dir
=
1
;
else
entry
->
is_dir
=
0
;
#if FATFS_INC_TIME_DATE_SUPPORT
// Get time / dates
entry
->
create_time
=
((
uint16
)
directoryEntry
->
CrtTime
[
1
]
<<
8
)
|
directoryEntry
->
CrtTime
[
0
];
entry
->
create_date
=
((
uint16
)
directoryEntry
->
CrtDate
[
1
]
<<
8
)
|
directoryEntry
->
CrtDate
[
0
];
entry
->
access_date
=
((
uint16
)
directoryEntry
->
LstAccDate
[
1
]
<<
8
)
|
directoryEntry
->
LstAccDate
[
0
];
entry
->
write_time
=
((
uint16
)
directoryEntry
->
WrtTime
[
1
]
<<
8
)
|
directoryEntry
->
WrtTime
[
0
];
entry
->
write_date
=
((
uint16
)
directoryEntry
->
WrtDate
[
1
]
<<
8
)
|
directoryEntry
->
WrtDate
[
0
];
#endif
entry
->
size
=
FAT_HTONL
(
directoryEntry
->
FileSize
);
entry
->
cluster
=
(
FAT_HTONS
(
directoryEntry
->
FstClusHI
)
<<
16
)
|
FAT_HTONS
(
directoryEntry
->
FstClusLO
);
// Next starting position
dirls
->
offset
=
item
+
1
;
result
=
1
;
return
1
;
}
}
// end of for
// If reached end of the dir move onto next sector
dirls
->
sector
++
;
dirls
->
offset
=
0
;
}
else
break
;
}
return
result
;
}
#endif
Plugson/src/Lib/fat_io_lib/fat_access.h
0 → 100644
View file @
4bf43ab9
#ifndef __FAT_ACCESS_H__
#define __FAT_ACCESS_H__
#include "fat_defs.h"
#include "fat_opts.h"
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
#define FAT_INIT_OK 0
#define FAT_INIT_MEDIA_ACCESS_ERROR (-1)
#define FAT_INIT_INVALID_SECTOR_SIZE (-2)
#define FAT_INIT_INVALID_SIGNATURE (-3)
#define FAT_INIT_ENDIAN_ERROR (-4)
#define FAT_INIT_WRONG_FILESYS_TYPE (-5)
#define FAT_INIT_WRONG_PARTITION_TYPE (-6)
#define FAT_INIT_STRUCT_PACKING (-7)
#define FAT_DIR_ENTRIES_PER_SECTOR (FAT_SECTOR_SIZE / FAT_DIR_ENTRY_SIZE)
//-----------------------------------------------------------------------------
// Function Pointers
//-----------------------------------------------------------------------------
typedef
int
(
*
fn_diskio_read
)
(
uint32
sector
,
uint8
*
buffer
,
uint32
sector_count
);
typedef
int
(
*
fn_diskio_write
)(
uint32
sector
,
uint8
*
buffer
,
uint32
sector_count
);
//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
struct
disk_if
{
// User supplied function pointers for disk IO
fn_diskio_read
read_media
;
fn_diskio_write
write_media
;
};
// Forward declaration
struct
fat_buffer
;
struct
fat_buffer
{
uint8
sector
[
FAT_SECTOR_SIZE
*
FAT_BUFFER_SECTORS
];
uint32
address
;
int
dirty
;
uint8
*
ptr
;
// Next in chain of sector buffers
struct
fat_buffer
*
next
;
};
typedef
enum
eFatType
{
FAT_TYPE_16
,
FAT_TYPE_32
}
tFatType
;
struct
fatfs
{
// Filesystem globals
uint8
sectors_per_cluster
;
uint32
cluster_begin_lba
;
uint32
rootdir_first_cluster
;
uint32
rootdir_first_sector
;
uint32
rootdir_sectors
;
uint32
fat_begin_lba
;
uint16
fs_info_sector
;
uint32
lba_begin
;
uint32
fat_sectors
;
uint32
next_free_cluster
;
uint16
root_entry_count
;
uint16
reserved_sectors
;
uint8
num_of_fats
;
tFatType
fat_type
;
// Disk/Media API
struct
disk_if
disk_io
;
// [Optional] Thread Safety
void
(
*
fl_lock
)(
void
);
void
(
*
fl_unlock
)(
void
);
// Working buffer
struct
fat_buffer
currentsector
;
// FAT Buffer
struct
fat_buffer
*
fat_buffer_head
;
struct
fat_buffer
fat_buffers
[
FAT_BUFFERS
];
};
struct
fs_dir_list_status
{
uint32
sector
;
uint32
cluster
;
uint8
offset
;
};
struct
fs_dir_ent
{
char
filename
[
FATFS_MAX_LONG_FILENAME
];
uint8
is_dir
;
uint32
cluster
;
uint32
size
;
#if FATFS_INC_TIME_DATE_SUPPORT
uint16
access_date
;
uint16
write_time
;
uint16
write_date
;
uint16
create_date
;
uint16
create_time
;
#endif
};
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
int
fatfs_init
(
struct
fatfs
*
fs
);
uint32
fatfs_lba_of_cluster
(
struct
fatfs
*
fs
,
uint32
Cluster_Number
);
int
fatfs_sector_reader
(
struct
fatfs
*
fs
,
uint32
Startcluster
,
uint32
offset
,
uint8
*
target
);
int
fatfs_sector_read
(
struct
fatfs
*
fs
,
uint32
lba
,
uint8
*
target
,
uint32
count
);
int
fatfs_sector_write
(
struct
fatfs
*
fs
,
uint32
lba
,
uint8
*
target
,
uint32
count
);
int
fatfs_read_sector
(
struct
fatfs
*
fs
,
uint32
cluster
,
uint32
sector
,
uint8
*
target
);
int
fatfs_write_sector
(
struct
fatfs
*
fs
,
uint32
cluster
,
uint32
sector
,
uint8
*
target
);
void
fatfs_show_details
(
struct
fatfs
*
fs
);
uint32
fatfs_get_root_cluster
(
struct
fatfs
*
fs
);
uint32
fatfs_get_file_entry
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
nametofind
,
struct
fat_dir_entry
*
sfEntry
);
int
fatfs_sfn_exists
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
shortname
);
int
fatfs_update_file_length
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
shortname
,
uint32
fileLength
);
int
fatfs_mark_file_deleted
(
struct
fatfs
*
fs
,
uint32
Cluster
,
char
*
shortname
);
void
fatfs_list_directory_start
(
struct
fatfs
*
fs
,
struct
fs_dir_list_status
*
dirls
,
uint32
StartCluster
);
int
fatfs_list_directory_next
(
struct
fatfs
*
fs
,
struct
fs_dir_list_status
*
dirls
,
struct
fs_dir_ent
*
entry
);
int
fatfs_update_timestamps
(
struct
fat_dir_entry
*
directoryEntry
,
int
create
,
int
modify
,
int
access
);
#endif
Plugson/src/Lib/fat_io_lib/fat_cache.c
0 → 100644
View file @
4bf43ab9
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// FAT File IO Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <string.h>
#include "fat_cache.h"
// Per file cluster chain caching used to improve performance.
// This does not have to be enabled for architectures with low
// memory space.
//-----------------------------------------------------------------------------
// fatfs_cache_init:
//-----------------------------------------------------------------------------
int
fatfs_cache_init
(
struct
fatfs
*
fs
,
FL_FILE
*
file
)
{
#ifdef FAT_CLUSTER_CACHE_ENTRIES
int
i
;
for
(
i
=
0
;
i
<
FAT_CLUSTER_CACHE_ENTRIES
;
i
++
)
{
file
->
cluster_cache_idx
[
i
]
=
0xFFFFFFFF
;
// Not used
file
->
cluster_cache_data
[
i
]
=
0
;
}
#endif
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_cache_get_next_cluster:
//-----------------------------------------------------------------------------
int
fatfs_cache_get_next_cluster
(
struct
fatfs
*
fs
,
FL_FILE
*
file
,
uint32
clusterIdx
,
uint32
*
pNextCluster
)
{
#ifdef FAT_CLUSTER_CACHE_ENTRIES
uint32
slot
=
clusterIdx
%
FAT_CLUSTER_CACHE_ENTRIES
;
if
(
file
->
cluster_cache_idx
[
slot
]
==
clusterIdx
)
{
*
pNextCluster
=
file
->
cluster_cache_data
[
slot
];
return
1
;
}
#endif
return
0
;
}
//-----------------------------------------------------------------------------
// fatfs_cache_set_next_cluster:
//-----------------------------------------------------------------------------
int
fatfs_cache_set_next_cluster
(
struct
fatfs
*
fs
,
FL_FILE
*
file
,
uint32
clusterIdx
,
uint32
nextCluster
)
{
#ifdef FAT_CLUSTER_CACHE_ENTRIES
uint32
slot
=
clusterIdx
%
FAT_CLUSTER_CACHE_ENTRIES
;
if
(
file
->
cluster_cache_idx
[
slot
]
==
clusterIdx
)
file
->
cluster_cache_data
[
slot
]
=
nextCluster
;
else
{
file
->
cluster_cache_idx
[
slot
]
=
clusterIdx
;
file
->
cluster_cache_data
[
slot
]
=
nextCluster
;
}
#endif
return
1
;
}
Plugson/src/Lib/fat_io_lib/fat_cache.h
0 → 100644
View file @
4bf43ab9
#ifndef __FAT_CACHE_H__
#define __FAT_CACHE_H__
#include "fat_filelib.h"
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
int
fatfs_cache_init
(
struct
fatfs
*
fs
,
FL_FILE
*
file
);
int
fatfs_cache_get_next_cluster
(
struct
fatfs
*
fs
,
FL_FILE
*
file
,
uint32
clusterIdx
,
uint32
*
pNextCluster
);
int
fatfs_cache_set_next_cluster
(
struct
fatfs
*
fs
,
FL_FILE
*
file
,
uint32
clusterIdx
,
uint32
nextCluster
);
#endif
Plugson/src/Lib/fat_io_lib/fat_defs.h
0 → 100644
View file @
4bf43ab9
#ifndef __FAT_DEFS_H__
#define __FAT_DEFS_H__
#include "fat_opts.h"
#include "fat_types.h"
//-----------------------------------------------------------------------------
// FAT32 Offsets
// Name Offset
//-----------------------------------------------------------------------------
// Boot Sector
#define BS_JMPBOOT 0 // Length = 3
#define BS_OEMNAME 3 // Length = 8
#define BPB_BYTSPERSEC 11 // Length = 2
#define BPB_SECPERCLUS 13 // Length = 1
#define BPB_RSVDSECCNT 14 // Length = 2
#define BPB_NUMFATS 16 // Length = 1
#define BPB_ROOTENTCNT 17 // Length = 2
#define BPB_TOTSEC16 19 // Length = 2
#define BPB_MEDIA 21 // Length = 1
#define BPB_FATSZ16 22 // Length = 2
#define BPB_SECPERTRK 24 // Length = 2
#define BPB_NUMHEADS 26 // Length = 2
#define BPB_HIDDSEC 28 // Length = 4
#define BPB_TOTSEC32 32 // Length = 4
// FAT 12/16
#define BS_FAT_DRVNUM 36 // Length = 1
#define BS_FAT_BOOTSIG 38 // Length = 1
#define BS_FAT_VOLID 39 // Length = 4
#define BS_FAT_VOLLAB 43 // Length = 11
#define BS_FAT_FILSYSTYPE 54 // Length = 8
// FAT 32
#define BPB_FAT32_FATSZ32 36 // Length = 4
#define BPB_FAT32_EXTFLAGS 40 // Length = 2
#define BPB_FAT32_FSVER 42 // Length = 2
#define BPB_FAT32_ROOTCLUS 44 // Length = 4
#define BPB_FAT32_FSINFO 48 // Length = 2
#define BPB_FAT32_BKBOOTSEC 50 // Length = 2
#define BS_FAT32_DRVNUM 64 // Length = 1
#define BS_FAT32_BOOTSIG 66 // Length = 1
#define BS_FAT32_VOLID 67 // Length = 4
#define BS_FAT32_VOLLAB 71 // Length = 11
#define BS_FAT32_FILSYSTYPE 82 // Length = 8
//-----------------------------------------------------------------------------
// FAT Types
//-----------------------------------------------------------------------------
#define FAT_TYPE_FAT12 1
#define FAT_TYPE_FAT16 2
#define FAT_TYPE_FAT32 3
//-----------------------------------------------------------------------------
// FAT32 Specific Statics
//-----------------------------------------------------------------------------
#define SIGNATURE_POSITION 510
#define SIGNATURE_VALUE 0xAA55
#define PARTITION1_TYPECODE_LOCATION 450
#define FAT32_TYPECODE1 0x0B
#define FAT32_TYPECODE2 0x0C
#define PARTITION1_LBA_BEGIN_LOCATION 454
#define PARTITION1_SIZE_LOCATION 458
#define FAT_DIR_ENTRY_SIZE 32
#define FAT_SFN_SIZE_FULL 11
#define FAT_SFN_SIZE_PARTIAL 8
//-----------------------------------------------------------------------------
// FAT32 File Attributes and Types
//-----------------------------------------------------------------------------
#define FILE_ATTR_READ_ONLY 0x01
#define FILE_ATTR_HIDDEN 0x02
#define FILE_ATTR_SYSTEM 0x04
#define FILE_ATTR_SYSHID 0x06
#define FILE_ATTR_VOLUME_ID 0x08
#define FILE_ATTR_DIRECTORY 0x10
#define FILE_ATTR_ARCHIVE 0x20
#define FILE_ATTR_LFN_TEXT 0x0F
#define FILE_HEADER_BLANK 0x00
#define FILE_HEADER_DELETED 0xE5
#define FILE_TYPE_DIR 0x10
#define FILE_TYPE_FILE 0x20
//-----------------------------------------------------------------------------
// Time / Date details
//-----------------------------------------------------------------------------
#define FAT_TIME_HOURS_SHIFT 11
#define FAT_TIME_HOURS_MASK 0x1F
#define FAT_TIME_MINUTES_SHIFT 5
#define FAT_TIME_MINUTES_MASK 0x3F
#define FAT_TIME_SECONDS_SHIFT 0
#define FAT_TIME_SECONDS_MASK 0x1F
#define FAT_TIME_SECONDS_SCALE 2
#define FAT_DATE_YEAR_SHIFT 9
#define FAT_DATE_YEAR_MASK 0x7F
#define FAT_DATE_MONTH_SHIFT 5
#define FAT_DATE_MONTH_MASK 0xF
#define FAT_DATE_DAY_SHIFT 0
#define FAT_DATE_DAY_MASK 0x1F
#define FAT_DATE_YEAR_OFFSET 1980
//-----------------------------------------------------------------------------
// Other Defines
//-----------------------------------------------------------------------------
#define FAT32_LAST_CLUSTER 0xFFFFFFFF
#define FAT32_INVALID_CLUSTER 0xFFFFFFFF
STRUCT_PACK_BEGIN
struct
fat_dir_entry
STRUCT_PACK
{
uint8
Name
[
11
];
uint8
Attr
;
uint8
NTRes
;
uint8
CrtTimeTenth
;
uint8
CrtTime
[
2
];
uint8
CrtDate
[
2
];
uint8
LstAccDate
[
2
];
uint16
FstClusHI
;
uint8
WrtTime
[
2
];
uint8
WrtDate
[
2
];
uint16
FstClusLO
;
uint32
FileSize
;
}
STRUCT_PACKED
;
STRUCT_PACK_END
#endif
Plugson/src/Lib/fat_io_lib/fat_filelib.c
0 → 100644
View file @
4bf43ab9
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// FAT File IO Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <stdlib.h>
#include <string.h>
#include "fat_defs.h"
#include "fat_access.h"
#include "fat_table.h"
#include "fat_write.h"
#include "fat_misc.h"
#include "fat_string.h"
#include "fat_filelib.h"
#include "fat_cache.h"
//-----------------------------------------------------------------------------
// Locals
//-----------------------------------------------------------------------------
static
FL_FILE
_files
[
FATFS_MAX_OPEN_FILES
];
static
int
_filelib_init
=
0
;
static
int
_filelib_valid
=
0
;
static
struct
fatfs
_fs
;
static
struct
fat_list
_open_file_list
;
static
struct
fat_list
_free_file_list
;
//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------
// Macro for checking if file lib is initialised
#define CHECK_FL_INIT() { if (_filelib_init==0) fl_init(); }
#define FL_LOCK(a) do { if ((a)->fl_lock) (a)->fl_lock(); } while (0)
#define FL_UNLOCK(a) do { if ((a)->fl_unlock) (a)->fl_unlock(); } while (0)
//-----------------------------------------------------------------------------
// Local Functions
//-----------------------------------------------------------------------------
static
void
_fl_init
();
//-----------------------------------------------------------------------------
// _allocate_file: Find a slot in the open files buffer for a new file
//-----------------------------------------------------------------------------
static
FL_FILE
*
_allocate_file
(
void
)
{
// Allocate free file
struct
fat_node
*
node
=
fat_list_pop_head
(
&
_free_file_list
);
// Add to open list
if
(
node
)
fat_list_insert_last
(
&
_open_file_list
,
node
);
return
fat_list_entry
(
node
,
FL_FILE
,
list_node
);
}
//-----------------------------------------------------------------------------
// _check_file_open: Returns true if the file is already open
//-----------------------------------------------------------------------------
static
int
_check_file_open
(
FL_FILE
*
file
)
{
struct
fat_node
*
node
;
// Compare open files
fat_list_for_each
(
&
_open_file_list
,
node
)
{
FL_FILE
*
openFile
=
fat_list_entry
(
node
,
FL_FILE
,
list_node
);
// If not the current file
if
(
openFile
!=
file
)
{
// Compare path and name
if
(
(
fatfs_compare_names
(
openFile
->
path
,
file
->
path
))
&&
(
fatfs_compare_names
(
openFile
->
filename
,
file
->
filename
))
)
return
1
;
}
}
return
0
;
}
//-----------------------------------------------------------------------------
// _free_file: Free open file handle
//-----------------------------------------------------------------------------
static
void
_free_file
(
FL_FILE
*
file
)
{
// Remove from open list
fat_list_remove
(
&
_open_file_list
,
&
file
->
list_node
);
// Add to free list
fat_list_insert_last
(
&
_free_file_list
,
&
file
->
list_node
);
}
//-----------------------------------------------------------------------------
// Low Level
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// _open_directory: Cycle through path string to find the start cluster
// address of the highest subdir.
//-----------------------------------------------------------------------------
static
int
_open_directory
(
char
*
path
,
uint32
*
pathCluster
)
{
int
levels
;
int
sublevel
;
char
currentfolder
[
FATFS_MAX_LONG_FILENAME
];
struct
fat_dir_entry
sfEntry
;
uint32
startcluster
;
// Set starting cluster to root cluster
startcluster
=
fatfs_get_root_cluster
(
&
_fs
);
// Find number of levels
levels
=
fatfs_total_path_levels
(
path
);
// Cycle through each level and get the start sector
for
(
sublevel
=
0
;
sublevel
<
(
levels
+
1
);
sublevel
++
)
{
if
(
fatfs_get_substring
(
path
,
sublevel
,
currentfolder
,
sizeof
(
currentfolder
))
==
-
1
)
return
0
;
// Find clusteraddress for folder (currentfolder)
if
(
fatfs_get_file_entry
(
&
_fs
,
startcluster
,
currentfolder
,
&
sfEntry
))
{
// Check entry is folder
if
(
fatfs_entry_is_dir
(
&
sfEntry
))
startcluster
=
((
FAT_HTONS
((
uint32
)
sfEntry
.
FstClusHI
))
<<
16
)
+
FAT_HTONS
(
sfEntry
.
FstClusLO
);
else
return
0
;
}
else
return
0
;
}
*
pathCluster
=
startcluster
;
return
1
;
}
//-----------------------------------------------------------------------------
// _create_directory: Cycle through path string and create the end directory
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
static
int
_create_directory
(
char
*
path
)
{
FL_FILE
*
file
;
struct
fat_dir_entry
sfEntry
;
char
shortFilename
[
FAT_SFN_SIZE_FULL
];
int
tailNum
=
0
;
int
i
;
// Allocate a new file handle
file
=
_allocate_file
();
if
(
!
file
)
return
0
;
// Clear filename
memset
(
file
->
path
,
'\0'
,
sizeof
(
file
->
path
));
memset
(
file
->
filename
,
'\0'
,
sizeof
(
file
->
filename
));
// Split full path into filename and directory path
if
(
fatfs_split_path
((
char
*
)
path
,
file
->
path
,
sizeof
(
file
->
path
),
file
->
filename
,
sizeof
(
file
->
filename
))
==
-
1
)
{
_free_file
(
file
);
return
0
;
}
// Check if file already open
if
(
_check_file_open
(
file
))
{
_free_file
(
file
);
return
0
;
}
// If file is in the root dir
if
(
file
->
path
[
0
]
==
0
)
file
->
parentcluster
=
fatfs_get_root_cluster
(
&
_fs
);
else
{
// Find parent directory start cluster
if
(
!
_open_directory
(
file
->
path
,
&
file
->
parentcluster
))
{
_free_file
(
file
);
return
0
;
}
}
// Check if same filename exists in directory
if
(
fatfs_get_file_entry
(
&
_fs
,
file
->
parentcluster
,
file
->
filename
,
&
sfEntry
)
==
1
)
{
_free_file
(
file
);
return
0
;
}
file
->
startcluster
=
0
;
// Create the file space for the folder (at least one clusters worth!)
if
(
!
fatfs_allocate_free_space
(
&
_fs
,
1
,
&
file
->
startcluster
,
1
))
{
_free_file
(
file
);
return
0
;
}
// Erase new directory cluster
memset
(
file
->
file_data_sector
,
0x00
,
FAT_SECTOR_SIZE
);
for
(
i
=
0
;
i
<
_fs
.
sectors_per_cluster
;
i
++
)
{
if
(
!
fatfs_write_sector
(
&
_fs
,
file
->
startcluster
,
i
,
file
->
file_data_sector
))
{
_free_file
(
file
);
return
0
;
}
}
#if FATFS_INC_LFN_SUPPORT
// Generate a short filename & tail
tailNum
=
0
;
do
{
// Create a standard short filename (without tail)
fatfs_lfn_create_sfn
(
shortFilename
,
file
->
filename
);
// If second hit or more, generate a ~n tail
if
(
tailNum
!=
0
)
fatfs_lfn_generate_tail
((
char
*
)
file
->
shortfilename
,
shortFilename
,
tailNum
);
// Try with no tail if first entry
else
memcpy
(
file
->
shortfilename
,
shortFilename
,
FAT_SFN_SIZE_FULL
);
// Check if entry exists already or not
if
(
fatfs_sfn_exists
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
shortfilename
)
==
0
)
break
;
tailNum
++
;
}
while
(
tailNum
<
9999
);
// We reached the max number of duplicate short file names (unlikely!)
if
(
tailNum
==
9999
)
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
0
;
}
#else
// Create a standard short filename (without tail)
if
(
!
fatfs_lfn_create_sfn
(
shortFilename
,
file
->
filename
))
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
0
;
}
// Copy to SFN space
memcpy
(
file
->
shortfilename
,
shortFilename
,
FAT_SFN_SIZE_FULL
);
// Check if entry exists already
if
(
fatfs_sfn_exists
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
shortfilename
))
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
0
;
}
#endif
// Add file to disk
if
(
!
fatfs_add_file_entry
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
filename
,
(
char
*
)
file
->
shortfilename
,
file
->
startcluster
,
0
,
1
))
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
0
;
}
// General
file
->
filelength
=
0
;
file
->
bytenum
=
0
;
file
->
file_data_address
=
0xFFFFFFFF
;
file
->
file_data_dirty
=
0
;
file
->
filelength_changed
=
0
;
// Quick lookup for next link in the chain
file
->
last_fat_lookup
.
ClusterIdx
=
0xFFFFFFFF
;
file
->
last_fat_lookup
.
CurrentCluster
=
0xFFFFFFFF
;
fatfs_fat_purge
(
&
_fs
);
_free_file
(
file
);
return
1
;
}
#endif
//-----------------------------------------------------------------------------
// _open_file: Open a file for reading
//-----------------------------------------------------------------------------
static
FL_FILE
*
_open_file
(
const
char
*
path
)
{
FL_FILE
*
file
;
struct
fat_dir_entry
sfEntry
;
// Allocate a new file handle
file
=
_allocate_file
();
if
(
!
file
)
return
NULL
;
// Clear filename
memset
(
file
->
path
,
'\0'
,
sizeof
(
file
->
path
));
memset
(
file
->
filename
,
'\0'
,
sizeof
(
file
->
filename
));
// Split full path into filename and directory path
if
(
fatfs_split_path
((
char
*
)
path
,
file
->
path
,
sizeof
(
file
->
path
),
file
->
filename
,
sizeof
(
file
->
filename
))
==
-
1
)
{
_free_file
(
file
);
return
NULL
;
}
// Check if file already open
if
(
_check_file_open
(
file
))
{
_free_file
(
file
);
return
NULL
;
}
// If file is in the root dir
if
(
file
->
path
[
0
]
==
0
)
file
->
parentcluster
=
fatfs_get_root_cluster
(
&
_fs
);
else
{
// Find parent directory start cluster
if
(
!
_open_directory
(
file
->
path
,
&
file
->
parentcluster
))
{
_free_file
(
file
);
return
NULL
;
}
}
// Using dir cluster address search for filename
if
(
fatfs_get_file_entry
(
&
_fs
,
file
->
parentcluster
,
file
->
filename
,
&
sfEntry
))
// Make sure entry is file not dir!
if
(
fatfs_entry_is_file
(
&
sfEntry
))
{
// Initialise file details
memcpy
(
file
->
shortfilename
,
sfEntry
.
Name
,
FAT_SFN_SIZE_FULL
);
file
->
filelength
=
FAT_HTONL
(
sfEntry
.
FileSize
);
file
->
bytenum
=
0
;
file
->
startcluster
=
((
FAT_HTONS
((
uint32
)
sfEntry
.
FstClusHI
))
<<
16
)
+
FAT_HTONS
(
sfEntry
.
FstClusLO
);
file
->
file_data_address
=
0xFFFFFFFF
;
file
->
file_data_dirty
=
0
;
file
->
filelength_changed
=
0
;
// Quick lookup for next link in the chain
file
->
last_fat_lookup
.
ClusterIdx
=
0xFFFFFFFF
;
file
->
last_fat_lookup
.
CurrentCluster
=
0xFFFFFFFF
;
fatfs_cache_init
(
&
_fs
,
file
);
fatfs_fat_purge
(
&
_fs
);
return
file
;
}
_free_file
(
file
);
return
NULL
;
}
//-----------------------------------------------------------------------------
// _create_file: Create a new file
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
static
FL_FILE
*
_create_file
(
const
char
*
filename
)
{
FL_FILE
*
file
;
struct
fat_dir_entry
sfEntry
;
char
shortFilename
[
FAT_SFN_SIZE_FULL
];
int
tailNum
=
0
;
// No write access?
if
(
!
_fs
.
disk_io
.
write_media
)
return
NULL
;
// Allocate a new file handle
file
=
_allocate_file
();
if
(
!
file
)
return
NULL
;
// Clear filename
memset
(
file
->
path
,
'\0'
,
sizeof
(
file
->
path
));
memset
(
file
->
filename
,
'\0'
,
sizeof
(
file
->
filename
));
// Split full path into filename and directory path
if
(
fatfs_split_path
((
char
*
)
filename
,
file
->
path
,
sizeof
(
file
->
path
),
file
->
filename
,
sizeof
(
file
->
filename
))
==
-
1
)
{
_free_file
(
file
);
return
NULL
;
}
// Check if file already open
if
(
_check_file_open
(
file
))
{
_free_file
(
file
);
return
NULL
;
}
// If file is in the root dir
if
(
file
->
path
[
0
]
==
0
)
file
->
parentcluster
=
fatfs_get_root_cluster
(
&
_fs
);
else
{
// Find parent directory start cluster
if
(
!
_open_directory
(
file
->
path
,
&
file
->
parentcluster
))
{
_free_file
(
file
);
return
NULL
;
}
}
// Check if same filename exists in directory
if
(
fatfs_get_file_entry
(
&
_fs
,
file
->
parentcluster
,
file
->
filename
,
&
sfEntry
)
==
1
)
{
_free_file
(
file
);
return
NULL
;
}
file
->
startcluster
=
0
;
// Create the file space for the file (at least one clusters worth!)
if
(
!
fatfs_allocate_free_space
(
&
_fs
,
1
,
&
file
->
startcluster
,
1
))
{
_free_file
(
file
);
return
NULL
;
}
#if FATFS_INC_LFN_SUPPORT
// Generate a short filename & tail
tailNum
=
0
;
do
{
// Create a standard short filename (without tail)
fatfs_lfn_create_sfn
(
shortFilename
,
file
->
filename
);
// If second hit or more, generate a ~n tail
if
(
tailNum
!=
0
)
fatfs_lfn_generate_tail
((
char
*
)
file
->
shortfilename
,
shortFilename
,
tailNum
);
// Try with no tail if first entry
else
memcpy
(
file
->
shortfilename
,
shortFilename
,
FAT_SFN_SIZE_FULL
);
// Check if entry exists already or not
if
(
fatfs_sfn_exists
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
shortfilename
)
==
0
)
break
;
tailNum
++
;
}
while
(
tailNum
<
9999
);
// We reached the max number of duplicate short file names (unlikely!)
if
(
tailNum
==
9999
)
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
NULL
;
}
#else
// Create a standard short filename (without tail)
if
(
!
fatfs_lfn_create_sfn
(
shortFilename
,
file
->
filename
))
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
NULL
;
}
// Copy to SFN space
memcpy
(
file
->
shortfilename
,
shortFilename
,
FAT_SFN_SIZE_FULL
);
// Check if entry exists already
if
(
fatfs_sfn_exists
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
shortfilename
))
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
NULL
;
}
#endif
// Add file to disk
if
(
!
fatfs_add_file_entry
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
filename
,
(
char
*
)
file
->
shortfilename
,
file
->
startcluster
,
0
,
0
))
{
// Delete allocated space
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
);
_free_file
(
file
);
return
NULL
;
}
// General
file
->
filelength
=
0
;
file
->
bytenum
=
0
;
file
->
file_data_address
=
0xFFFFFFFF
;
file
->
file_data_dirty
=
0
;
file
->
filelength_changed
=
0
;
// Quick lookup for next link in the chain
file
->
last_fat_lookup
.
ClusterIdx
=
0xFFFFFFFF
;
file
->
last_fat_lookup
.
CurrentCluster
=
0xFFFFFFFF
;
fatfs_cache_init
(
&
_fs
,
file
);
fatfs_fat_purge
(
&
_fs
);
return
file
;
}
#endif
//-----------------------------------------------------------------------------
// _read_sectors: Read sector(s) from disk to file
//-----------------------------------------------------------------------------
static
uint32
_read_sectors
(
FL_FILE
*
file
,
uint32
offset
,
uint8
*
buffer
,
uint32
count
)
{
uint32
Sector
=
0
;
uint32
ClusterIdx
=
0
;
uint32
Cluster
=
0
;
uint32
i
;
uint32
lba
;
// Find cluster index within file & sector with cluster
ClusterIdx
=
offset
/
_fs
.
sectors_per_cluster
;
Sector
=
offset
-
(
ClusterIdx
*
_fs
.
sectors_per_cluster
);
// Limit number of sectors read to the number remaining in this cluster
if
((
Sector
+
count
)
>
_fs
.
sectors_per_cluster
)
count
=
_fs
.
sectors_per_cluster
-
Sector
;
// Quick lookup for next link in the chain
if
(
ClusterIdx
==
file
->
last_fat_lookup
.
ClusterIdx
)
Cluster
=
file
->
last_fat_lookup
.
CurrentCluster
;
// Else walk the chain
else
{
// Starting from last recorded cluster?
if
(
ClusterIdx
&&
ClusterIdx
==
file
->
last_fat_lookup
.
ClusterIdx
+
1
)
{
i
=
file
->
last_fat_lookup
.
ClusterIdx
;
Cluster
=
file
->
last_fat_lookup
.
CurrentCluster
;
}
// Start searching from the beginning..
else
{
// Set start of cluster chain to initial value
i
=
0
;
Cluster
=
file
->
startcluster
;
}
// Follow chain to find cluster to read
for
(
;
i
<
ClusterIdx
;
i
++
)
{
uint32
nextCluster
;
// Does the entry exist in the cache?
if
(
!
fatfs_cache_get_next_cluster
(
&
_fs
,
file
,
i
,
&
nextCluster
))
{
// Scan file linked list to find next entry
nextCluster
=
fatfs_find_next_cluster
(
&
_fs
,
Cluster
);
// Push entry into cache
fatfs_cache_set_next_cluster
(
&
_fs
,
file
,
i
,
nextCluster
);
}
Cluster
=
nextCluster
;
}
// Record current cluster lookup details (if valid)
if
(
Cluster
!=
FAT32_LAST_CLUSTER
)
{
file
->
last_fat_lookup
.
CurrentCluster
=
Cluster
;
file
->
last_fat_lookup
.
ClusterIdx
=
ClusterIdx
;
}
}
// If end of cluster chain then return false
if
(
Cluster
==
FAT32_LAST_CLUSTER
)
return
0
;
// Calculate sector address
lba
=
fatfs_lba_of_cluster
(
&
_fs
,
Cluster
)
+
Sector
;
// Read sector of file
if
(
fatfs_sector_read
(
&
_fs
,
lba
,
buffer
,
count
))
return
count
;
else
return
0
;
}
//-----------------------------------------------------------------------------
// External API
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// fl_init: Initialise library
//-----------------------------------------------------------------------------
void
fl_init
(
void
)
{
int
i
;
fat_list_init
(
&
_free_file_list
);
fat_list_init
(
&
_open_file_list
);
// Add all file objects to free list
for
(
i
=
0
;
i
<
FATFS_MAX_OPEN_FILES
;
i
++
)
fat_list_insert_last
(
&
_free_file_list
,
&
_files
[
i
].
list_node
);
_filelib_init
=
1
;
}
//-----------------------------------------------------------------------------
// fl_attach_locks:
//-----------------------------------------------------------------------------
void
fl_attach_locks
(
void
(
*
lock
)(
void
),
void
(
*
unlock
)(
void
))
{
_fs
.
fl_lock
=
lock
;
_fs
.
fl_unlock
=
unlock
;
}
//-----------------------------------------------------------------------------
// fl_attach_media:
//-----------------------------------------------------------------------------
int
fl_attach_media
(
fn_diskio_read
rd
,
fn_diskio_write
wr
)
{
int
res
;
// If first call to library, initialise
CHECK_FL_INIT
();
_fs
.
disk_io
.
read_media
=
rd
;
_fs
.
disk_io
.
write_media
=
wr
;
// Initialise FAT parameters
if
((
res
=
fatfs_init
(
&
_fs
))
!=
FAT_INIT_OK
)
{
FAT_PRINTF
((
"FAT_FS: Error could not load FAT details (%d)!
\r\n
"
,
res
));
return
res
;
}
_filelib_valid
=
1
;
return
FAT_INIT_OK
;
}
//-----------------------------------------------------------------------------
// fl_shutdown: Call before shutting down system
//-----------------------------------------------------------------------------
void
fl_shutdown
(
void
)
{
// If first call to library, initialise
CHECK_FL_INIT
();
FL_LOCK
(
&
_fs
);
fatfs_fat_purge
(
&
_fs
);
FL_UNLOCK
(
&
_fs
);
}
//-----------------------------------------------------------------------------
// fopen: Open or Create a file for reading or writing
//-----------------------------------------------------------------------------
void
*
fl_fopen
(
const
char
*
path
,
const
char
*
mode
)
{
int
i
;
FL_FILE
*
file
;
uint8
flags
=
0
;
// If first call to library, initialise
CHECK_FL_INIT
();
if
(
!
_filelib_valid
)
return
NULL
;
if
(
!
path
||
!
mode
)
return
NULL
;
// Supported Modes:
// "r" Open a file for reading.
// The file must exist.
// "w" Create an empty file for writing.
// If a file with the same name already exists its content is erased and the file is treated as a new empty file.
// "a" Append to a file.
// Writing operations append data at the end of the file.
// The file is created if it does not exist.
// "r+" Open a file for update both reading and writing.
// The file must exist.
// "w+" Create an empty file for both reading and writing.
// If a file with the same name already exists its content is erased and the file is treated as a new empty file.
// "a+" Open a file for reading and appending.
// All writing operations are performed at the end of the file, protecting the previous content to be overwritten.
// You can reposition (fseek, rewind) the internal pointer to anywhere in the file for reading, but writing operations
// will move it back to the end of file.
// The file is created if it does not exist.
for
(
i
=
0
;
i
<
(
int
)
strlen
(
mode
);
i
++
)
{
switch
(
mode
[
i
])
{
case
'r'
:
case
'R'
:
flags
|=
FILE_READ
;
break
;
case
'w'
:
case
'W'
:
flags
|=
FILE_WRITE
;
flags
|=
FILE_ERASE
;
flags
|=
FILE_CREATE
;
break
;
case
'a'
:
case
'A'
:
flags
|=
FILE_WRITE
;
flags
|=
FILE_APPEND
;
flags
|=
FILE_CREATE
;
break
;
case
'+'
:
if
(
flags
&
FILE_READ
)
flags
|=
FILE_WRITE
;
else
if
(
flags
&
FILE_WRITE
)
{
flags
|=
FILE_READ
;
flags
|=
FILE_ERASE
;
flags
|=
FILE_CREATE
;
}
else
if
(
flags
&
FILE_APPEND
)
{
flags
|=
FILE_READ
;
flags
|=
FILE_WRITE
;
flags
|=
FILE_APPEND
;
flags
|=
FILE_CREATE
;
}
break
;
case
'b'
:
case
'B'
:
flags
|=
FILE_BINARY
;
break
;
}
}
file
=
NULL
;
#if FATFS_INC_WRITE_SUPPORT == 0
// No write support!
flags
&=
~
(
FILE_CREATE
|
FILE_WRITE
|
FILE_APPEND
);
#endif
// No write access - remove write/modify flags
if
(
!
_fs
.
disk_io
.
write_media
)
flags
&=
~
(
FILE_CREATE
|
FILE_WRITE
|
FILE_APPEND
);
FL_LOCK
(
&
_fs
);
// Read
if
(
flags
&
FILE_READ
)
file
=
_open_file
(
path
);
// Create New
#if FATFS_INC_WRITE_SUPPORT
if
(
!
file
&&
(
flags
&
FILE_CREATE
))
file
=
_create_file
(
path
);
#endif
// Write Existing (and not open due to read or create)
if
(
!
(
flags
&
FILE_READ
))
if
((
flags
&
FILE_CREATE
)
&&
!
file
)
if
(
flags
&
(
FILE_WRITE
|
FILE_APPEND
))
file
=
_open_file
(
path
);
if
(
file
)
file
->
flags
=
flags
;
FL_UNLOCK
(
&
_fs
);
return
file
;
}
//-----------------------------------------------------------------------------
// _write_sectors: Write sector(s) to disk
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
static
uint32
_write_sectors
(
FL_FILE
*
file
,
uint32
offset
,
uint8
*
buf
,
uint32
count
)
{
uint32
SectorNumber
=
0
;
uint32
ClusterIdx
=
0
;
uint32
Cluster
=
0
;
uint32
LastCluster
=
FAT32_LAST_CLUSTER
;
uint32
i
;
uint32
lba
;
uint32
TotalWriteCount
=
count
;
// Find values for Cluster index & sector within cluster
ClusterIdx
=
offset
/
_fs
.
sectors_per_cluster
;
SectorNumber
=
offset
-
(
ClusterIdx
*
_fs
.
sectors_per_cluster
);
// Limit number of sectors written to the number remaining in this cluster
if
((
SectorNumber
+
count
)
>
_fs
.
sectors_per_cluster
)
count
=
_fs
.
sectors_per_cluster
-
SectorNumber
;
// Quick lookup for next link in the chain
if
(
ClusterIdx
==
file
->
last_fat_lookup
.
ClusterIdx
)
Cluster
=
file
->
last_fat_lookup
.
CurrentCluster
;
// Else walk the chain
else
{
// Starting from last recorded cluster?
if
(
ClusterIdx
&&
ClusterIdx
==
file
->
last_fat_lookup
.
ClusterIdx
+
1
)
{
i
=
file
->
last_fat_lookup
.
ClusterIdx
;
Cluster
=
file
->
last_fat_lookup
.
CurrentCluster
;
}
// Start searching from the beginning..
else
{
// Set start of cluster chain to initial value
i
=
0
;
Cluster
=
file
->
startcluster
;
}
// Follow chain to find cluster to read
for
(
;
i
<
ClusterIdx
;
i
++
)
{
uint32
nextCluster
;
// Does the entry exist in the cache?
if
(
!
fatfs_cache_get_next_cluster
(
&
_fs
,
file
,
i
,
&
nextCluster
))
{
// Scan file linked list to find next entry
nextCluster
=
fatfs_find_next_cluster
(
&
_fs
,
Cluster
);
// Push entry into cache
fatfs_cache_set_next_cluster
(
&
_fs
,
file
,
i
,
nextCluster
);
}
LastCluster
=
Cluster
;
Cluster
=
nextCluster
;
// Dont keep following a dead end
if
(
Cluster
==
FAT32_LAST_CLUSTER
)
break
;
}
// If we have reached the end of the chain, allocate more!
if
(
Cluster
==
FAT32_LAST_CLUSTER
)
{
// Add some more cluster(s) to the last good cluster chain
if
(
!
fatfs_add_free_space
(
&
_fs
,
&
LastCluster
,
(
TotalWriteCount
+
_fs
.
sectors_per_cluster
-
1
)
/
_fs
.
sectors_per_cluster
))
return
0
;
Cluster
=
LastCluster
;
}
// Record current cluster lookup details
file
->
last_fat_lookup
.
CurrentCluster
=
Cluster
;
file
->
last_fat_lookup
.
ClusterIdx
=
ClusterIdx
;
}
// Calculate write address
lba
=
fatfs_lba_of_cluster
(
&
_fs
,
Cluster
)
+
SectorNumber
;
if
(
fatfs_sector_write
(
&
_fs
,
lba
,
buf
,
count
))
return
count
;
else
return
0
;
}
#endif
//-----------------------------------------------------------------------------
// fl_fflush: Flush un-written data to the file
//-----------------------------------------------------------------------------
int
fl_fflush
(
void
*
f
)
{
#if FATFS_INC_WRITE_SUPPORT
FL_FILE
*
file
=
(
FL_FILE
*
)
f
;
// If first call to library, initialise
CHECK_FL_INIT
();
if
(
file
)
{
FL_LOCK
(
&
_fs
);
// If some write data still in buffer
if
(
file
->
file_data_dirty
)
{
// Write back current sector before loading next
if
(
_write_sectors
(
file
,
file
->
file_data_address
,
file
->
file_data_sector
,
1
))
file
->
file_data_dirty
=
0
;
}
FL_UNLOCK
(
&
_fs
);
}
#endif
return
0
;
}
//-----------------------------------------------------------------------------
// fl_fclose: Close an open file
//-----------------------------------------------------------------------------
void
fl_fclose
(
void
*
f
)
{
FL_FILE
*
file
=
(
FL_FILE
*
)
f
;
// If first call to library, initialise
CHECK_FL_INIT
();
if
(
file
)
{
FL_LOCK
(
&
_fs
);
// Flush un-written data to file
fl_fflush
(
f
);
// File size changed?
if
(
file
->
filelength_changed
)
{
#if FATFS_INC_WRITE_SUPPORT
// Update filesize in directory
fatfs_update_file_length
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
shortfilename
,
file
->
filelength
);
#endif
file
->
filelength_changed
=
0
;
}
file
->
bytenum
=
0
;
file
->
filelength
=
0
;
file
->
startcluster
=
0
;
file
->
file_data_address
=
0xFFFFFFFF
;
file
->
file_data_dirty
=
0
;
file
->
filelength_changed
=
0
;
// Free file handle
_free_file
(
file
);
fatfs_fat_purge
(
&
_fs
);
FL_UNLOCK
(
&
_fs
);
}
}
//-----------------------------------------------------------------------------
// fl_fgetc: Get a character in the stream
//-----------------------------------------------------------------------------
int
fl_fgetc
(
void
*
f
)
{
int
res
;
uint8
data
=
0
;
res
=
fl_fread
(
&
data
,
1
,
1
,
f
);
if
(
res
==
1
)
return
(
int
)
data
;
else
return
res
;
}
//-----------------------------------------------------------------------------
// fl_fgets: Get a string from a stream
//-----------------------------------------------------------------------------
char
*
fl_fgets
(
char
*
s
,
int
n
,
void
*
f
)
{
int
idx
=
0
;
// Space for null terminator?
if
(
n
>
0
)
{
// While space (+space for null terminator)
while
(
idx
<
(
n
-
1
))
{
int
ch
=
fl_fgetc
(
f
);
// EOF / Error?
if
(
ch
<
0
)
break
;
// Store character read from stream
s
[
idx
++
]
=
(
char
)
ch
;
// End of line?
if
(
ch
==
'\n'
)
break
;
}
if
(
idx
>
0
)
s
[
idx
]
=
'\0'
;
}
return
(
idx
>
0
)
?
s
:
0
;
}
//-----------------------------------------------------------------------------
// fl_fread: Read a block of data from the file
//-----------------------------------------------------------------------------
int
fl_fread
(
void
*
buffer
,
int
size
,
int
length
,
void
*
f
)
{
uint32
sector
;
uint32
offset
;
int
copyCount
;
int
count
=
size
*
length
;
int
bytesRead
=
0
;
FL_FILE
*
file
=
(
FL_FILE
*
)
f
;
// If first call to library, initialise
CHECK_FL_INIT
();
if
(
buffer
==
NULL
||
file
==
NULL
)
return
-
1
;
// No read permissions
if
(
!
(
file
->
flags
&
FILE_READ
))
return
-
1
;
// Nothing to be done
if
(
!
count
)
return
0
;
// Check if read starts past end of file
if
(
file
->
bytenum
>=
file
->
filelength
)
return
-
1
;
// Limit to file size
if
(
(
file
->
bytenum
+
count
)
>
file
->
filelength
)
count
=
file
->
filelength
-
file
->
bytenum
;
// Calculate start sector
sector
=
file
->
bytenum
/
FAT_SECTOR_SIZE
;
// Offset to start copying data from first sector
offset
=
file
->
bytenum
%
FAT_SECTOR_SIZE
;
while
(
bytesRead
<
count
)
{
// Read whole sector, read from media directly into target buffer
if
((
offset
==
0
)
&&
((
count
-
bytesRead
)
>=
FAT_SECTOR_SIZE
))
{
// Read as many sectors as possible into target buffer
uint32
sectorsRead
=
_read_sectors
(
file
,
sector
,
(
uint8
*
)((
uint8
*
)
buffer
+
bytesRead
),
(
count
-
bytesRead
)
/
FAT_SECTOR_SIZE
);
if
(
sectorsRead
)
{
// We have upto one sector to copy
copyCount
=
FAT_SECTOR_SIZE
*
sectorsRead
;
// Move onto next sector and reset copy offset
sector
+=
sectorsRead
;
offset
=
0
;
}
else
break
;
}
else
{
// Do we need to re-read the sector?
if
(
file
->
file_data_address
!=
sector
)
{
// Flush un-written data to file
if
(
file
->
file_data_dirty
)
fl_fflush
(
file
);
// Get LBA of sector offset within file
if
(
!
_read_sectors
(
file
,
sector
,
file
->
file_data_sector
,
1
))
// Read failed - out of range (probably)
break
;
file
->
file_data_address
=
sector
;
file
->
file_data_dirty
=
0
;
}
// We have upto one sector to copy
copyCount
=
FAT_SECTOR_SIZE
-
offset
;
// Only require some of this sector?
if
(
copyCount
>
(
count
-
bytesRead
))
copyCount
=
(
count
-
bytesRead
);
// Copy to application buffer
memcpy
(
(
uint8
*
)((
uint8
*
)
buffer
+
bytesRead
),
(
uint8
*
)(
file
->
file_data_sector
+
offset
),
copyCount
);
// Move onto next sector and reset copy offset
sector
++
;
offset
=
0
;
}
// Increase total read count
bytesRead
+=
copyCount
;
// Increment file pointer
file
->
bytenum
+=
copyCount
;
}
return
bytesRead
;
}
//-----------------------------------------------------------------------------
// fl_fseek: Seek to a specific place in the file
//-----------------------------------------------------------------------------
int
fl_fseek
(
void
*
f
,
long
offset
,
int
origin
)
{
FL_FILE
*
file
=
(
FL_FILE
*
)
f
;
int
res
=
-
1
;
// If first call to library, initialise
CHECK_FL_INIT
();
if
(
!
file
)
return
-
1
;
if
(
origin
==
SEEK_END
&&
offset
!=
0
)
return
-
1
;
FL_LOCK
(
&
_fs
);
// Invalidate file buffer
file
->
file_data_address
=
0xFFFFFFFF
;
file
->
file_data_dirty
=
0
;
if
(
origin
==
SEEK_SET
)
{
file
->
bytenum
=
(
uint32
)
offset
;
if
(
file
->
bytenum
>
file
->
filelength
)
file
->
bytenum
=
file
->
filelength
;
res
=
0
;
}
else
if
(
origin
==
SEEK_CUR
)
{
// Positive shift
if
(
offset
>=
0
)
{
file
->
bytenum
+=
offset
;
if
(
file
->
bytenum
>
file
->
filelength
)
file
->
bytenum
=
file
->
filelength
;
}
// Negative shift
else
{
// Make shift positive
offset
=
-
offset
;
// Limit to negative shift to start of file
if
((
uint32
)
offset
>
file
->
bytenum
)
file
->
bytenum
=
0
;
else
file
->
bytenum
-=
offset
;
}
res
=
0
;
}
else
if
(
origin
==
SEEK_END
)
{
file
->
bytenum
=
file
->
filelength
;
res
=
0
;
}
else
res
=
-
1
;
FL_UNLOCK
(
&
_fs
);
return
res
;
}
//-----------------------------------------------------------------------------
// fl_fgetpos: Get the current file position
//-----------------------------------------------------------------------------
int
fl_fgetpos
(
void
*
f
,
uint32
*
position
)
{
FL_FILE
*
file
=
(
FL_FILE
*
)
f
;
if
(
!
file
)
return
-
1
;
FL_LOCK
(
&
_fs
);
// Get position
*
position
=
file
->
bytenum
;
FL_UNLOCK
(
&
_fs
);
return
0
;
}
//-----------------------------------------------------------------------------
// fl_ftell: Get the current file position
//-----------------------------------------------------------------------------
long
fl_ftell
(
void
*
f
)
{
uint32
pos
=
0
;
fl_fgetpos
(
f
,
&
pos
);
return
(
long
)
pos
;
}
//-----------------------------------------------------------------------------
// fl_feof: Is the file pointer at the end of the stream?
//-----------------------------------------------------------------------------
int
fl_feof
(
void
*
f
)
{
FL_FILE
*
file
=
(
FL_FILE
*
)
f
;
int
res
;
if
(
!
file
)
return
-
1
;
FL_LOCK
(
&
_fs
);
if
(
file
->
bytenum
==
file
->
filelength
)
res
=
EOF
;
else
res
=
0
;
FL_UNLOCK
(
&
_fs
);
return
res
;
}
//-----------------------------------------------------------------------------
// fl_fputc: Write a character to the stream
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fl_fputc
(
int
c
,
void
*
f
)
{
uint8
data
=
(
uint8
)
c
;
int
res
;
res
=
fl_fwrite
(
&
data
,
1
,
1
,
f
);
if
(
res
==
1
)
return
c
;
else
return
res
;
}
#endif
//-----------------------------------------------------------------------------
// fl_fwrite: Write a block of data to the stream
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fl_fwrite
(
const
void
*
data
,
int
size
,
int
count
,
void
*
f
)
{
FL_FILE
*
file
=
(
FL_FILE
*
)
f
;
uint32
sector
;
uint32
offset
;
uint32
length
=
(
size
*
count
);
uint8
*
buffer
=
(
uint8
*
)
data
;
uint32
bytesWritten
=
0
;
uint32
copyCount
;
// If first call to library, initialise
CHECK_FL_INIT
();
if
(
!
file
)
return
-
1
;
FL_LOCK
(
&
_fs
);
// No write permissions
if
(
!
(
file
->
flags
&
FILE_WRITE
))
{
FL_UNLOCK
(
&
_fs
);
return
-
1
;
}
// Append writes to end of file
if
(
file
->
flags
&
FILE_APPEND
)
file
->
bytenum
=
file
->
filelength
;
// Else write to current position
// Calculate start sector
sector
=
file
->
bytenum
/
FAT_SECTOR_SIZE
;
// Offset to start copying data from first sector
offset
=
file
->
bytenum
%
FAT_SECTOR_SIZE
;
while
(
bytesWritten
<
length
)
{
// Whole sector or more to be written?
if
((
offset
==
0
)
&&
((
length
-
bytesWritten
)
>=
FAT_SECTOR_SIZE
))
{
uint32
sectorsWrote
;
// Buffered sector, flush back to disk
if
(
file
->
file_data_address
!=
0xFFFFFFFF
)
{
// Flush un-written data to file
if
(
file
->
file_data_dirty
)
fl_fflush
(
file
);
file
->
file_data_address
=
0xFFFFFFFF
;
file
->
file_data_dirty
=
0
;
}
// Write as many sectors as possible
sectorsWrote
=
_write_sectors
(
file
,
sector
,
(
uint8
*
)(
buffer
+
bytesWritten
),
(
length
-
bytesWritten
)
/
FAT_SECTOR_SIZE
);
copyCount
=
FAT_SECTOR_SIZE
*
sectorsWrote
;
// Increase total read count
bytesWritten
+=
copyCount
;
// Increment file pointer
file
->
bytenum
+=
copyCount
;
// Move onto next sector and reset copy offset
sector
+=
sectorsWrote
;
offset
=
0
;
if
(
!
sectorsWrote
)
break
;
}
else
{
// We have upto one sector to copy
copyCount
=
FAT_SECTOR_SIZE
-
offset
;
// Only require some of this sector?
if
(
copyCount
>
(
length
-
bytesWritten
))
copyCount
=
(
length
-
bytesWritten
);
// Do we need to read a new sector?
if
(
file
->
file_data_address
!=
sector
)
{
// Flush un-written data to file
if
(
file
->
file_data_dirty
)
fl_fflush
(
file
);
// If we plan to overwrite the whole sector, we don't need to read it first!
if
(
copyCount
!=
FAT_SECTOR_SIZE
)
{
// NOTE: This does not have succeed; if last sector of file
// reached, no valid data will be read in, but write will
// allocate some more space for new data.
// Get LBA of sector offset within file
if
(
!
_read_sectors
(
file
,
sector
,
file
->
file_data_sector
,
1
))
memset
(
file
->
file_data_sector
,
0x00
,
FAT_SECTOR_SIZE
);
}
file
->
file_data_address
=
sector
;
file
->
file_data_dirty
=
0
;
}
// Copy from application buffer into sector buffer
memcpy
((
uint8
*
)(
file
->
file_data_sector
+
offset
),
(
uint8
*
)(
buffer
+
bytesWritten
),
copyCount
);
// Mark buffer as dirty
file
->
file_data_dirty
=
1
;
// Increase total read count
bytesWritten
+=
copyCount
;
// Increment file pointer
file
->
bytenum
+=
copyCount
;
// Move onto next sector and reset copy offset
sector
++
;
offset
=
0
;
}
}
// Write increased extent of the file?
if
(
file
->
bytenum
>
file
->
filelength
)
{
// Increase file size to new point
file
->
filelength
=
file
->
bytenum
;
// We are changing the file length and this
// will need to be writen back at some point
file
->
filelength_changed
=
1
;
}
#if FATFS_INC_TIME_DATE_SUPPORT
// If time & date support is enabled, always force directory entry to be
// written in-order to update file modify / access time & date.
file
->
filelength_changed
=
1
;
#endif
FL_UNLOCK
(
&
_fs
);
return
(
size
*
count
);
}
#endif
//-----------------------------------------------------------------------------
// fl_fputs: Write a character string to the stream
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fl_fputs
(
const
char
*
str
,
void
*
f
)
{
int
len
=
(
int
)
strlen
(
str
);
int
res
=
fl_fwrite
(
str
,
1
,
len
,
f
);
if
(
res
==
len
)
return
len
;
else
return
res
;
}
#endif
//-----------------------------------------------------------------------------
// fl_remove: Remove a file from the filesystem
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fl_remove
(
const
char
*
filename
)
{
FL_FILE
*
file
;
int
res
=
-
1
;
FL_LOCK
(
&
_fs
);
// Use read_file as this will check if the file is already open!
file
=
fl_fopen
((
char
*
)
filename
,
"r"
);
if
(
file
)
{
// Delete allocated space
if
(
fatfs_free_cluster_chain
(
&
_fs
,
file
->
startcluster
))
{
// Remove directory entries
if
(
fatfs_mark_file_deleted
(
&
_fs
,
file
->
parentcluster
,
(
char
*
)
file
->
shortfilename
))
{
// Close the file handle (this should not write anything to the file
// as we have not changed the file since opening it!)
fl_fclose
(
file
);
res
=
0
;
}
}
}
FL_UNLOCK
(
&
_fs
);
return
res
;
}
#endif
//-----------------------------------------------------------------------------
// fl_createdirectory: Create a directory based on a path
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int
fl_createdirectory
(
const
char
*
path
)
{
int
res
;
// If first call to library, initialise
CHECK_FL_INIT
();
FL_LOCK
(
&
_fs
);
res
=
_create_directory
((
char
*
)
path
);
FL_UNLOCK
(
&
_fs
);
return
res
;
}
#endif
//-----------------------------------------------------------------------------
// fl_listdirectory: List a directory based on a path
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
void
fl_listdirectory
(
const
char
*
path
)
{
FL_DIR
dirstat
;
// If first call to library, initialise
CHECK_FL_INIT
();
FL_LOCK
(
&
_fs
);
FAT_PRINTF
((
"
\r\n
Directory %s
\r\n
"
,
path
));
if
(
fl_opendir
(
path
,
&
dirstat
))
{
struct
fs_dir_ent
dirent
;
while
(
fl_readdir
(
&
dirstat
,
&
dirent
)
==
0
)
{
#if FATFS_INC_TIME_DATE_SUPPORT
int
d
,
m
,
y
,
h
,
mn
,
s
;
fatfs_convert_from_fat_time
(
dirent
.
write_time
,
&
h
,
&
m
,
&
s
);
fatfs_convert_from_fat_date
(
dirent
.
write_date
,
&
d
,
&
mn
,
&
y
);
FAT_PRINTF
((
"%02d/%02d/%04d %02d:%02d "
,
d
,
mn
,
y
,
h
,
m
));
#endif
if
(
dirent
.
is_dir
)
{
FAT_PRINTF
((
"%s <DIR>
\r\n
"
,
dirent
.
filename
));
}
else
{
FAT_PRINTF
((
"%s [%d bytes]
\r\n
"
,
dirent
.
filename
,
dirent
.
size
));
}
}
fl_closedir
(
&
dirstat
);
}
FL_UNLOCK
(
&
_fs
);
}
#endif
//-----------------------------------------------------------------------------
// fl_opendir: Opens a directory for listing
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
FL_DIR
*
fl_opendir
(
const
char
*
path
,
FL_DIR
*
dir
)
{
int
levels
;
int
res
=
1
;
uint32
cluster
=
FAT32_INVALID_CLUSTER
;
// If first call to library, initialise
CHECK_FL_INIT
();
FL_LOCK
(
&
_fs
);
levels
=
fatfs_total_path_levels
((
char
*
)
path
)
+
1
;
// If path is in the root dir
if
(
levels
==
0
)
cluster
=
fatfs_get_root_cluster
(
&
_fs
);
// Find parent directory start cluster
else
res
=
_open_directory
((
char
*
)
path
,
&
cluster
);
if
(
res
)
fatfs_list_directory_start
(
&
_fs
,
dir
,
cluster
);
FL_UNLOCK
(
&
_fs
);
return
cluster
!=
FAT32_INVALID_CLUSTER
?
dir
:
0
;
}
#endif
//-----------------------------------------------------------------------------
// fl_readdir: Get next item in directory
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
int
fl_readdir
(
FL_DIR
*
dirls
,
fl_dirent
*
entry
)
{
int
res
=
0
;
// If first call to library, initialise
CHECK_FL_INIT
();
FL_LOCK
(
&
_fs
);
res
=
fatfs_list_directory_next
(
&
_fs
,
dirls
,
entry
);
FL_UNLOCK
(
&
_fs
);
return
res
?
0
:
-
1
;
}
#endif
//-----------------------------------------------------------------------------
// fl_closedir: Close directory after listing
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
int
fl_closedir
(
FL_DIR
*
dir
)
{
// Not used
return
0
;
}
#endif
//-----------------------------------------------------------------------------
// fl_is_dir: Is this a directory?
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
int
fl_is_dir
(
const
char
*
path
)
{
int
res
=
0
;
FL_DIR
dir
;
if
(
fl_opendir
(
path
,
&
dir
))
{
res
=
1
;
fl_closedir
(
&
dir
);
}
return
res
;
}
#endif
//-----------------------------------------------------------------------------
// fl_format: Format a partition with either FAT16 or FAT32 based on size
//-----------------------------------------------------------------------------
#if FATFS_INC_FORMAT_SUPPORT
int
fl_format
(
uint32
volume_sectors
,
const
char
*
name
)
{
return
fatfs_format
(
&
_fs
,
volume_sectors
,
name
);
}
#endif
/*FATFS_INC_FORMAT_SUPPORT*/
//-----------------------------------------------------------------------------
// fl_get_fs:
//-----------------------------------------------------------------------------
#ifdef FATFS_INC_TEST_HOOKS
struct
fatfs
*
fl_get_fs
(
void
)
{
return
&
_fs
;
}
#endif
Plugson/src/Lib/fat_io_lib/fat_filelib.h
0 → 100644
View file @
4bf43ab9
#ifndef __FAT_FILELIB_H__
#define __FAT_FILELIB_H__
#include "fat_opts.h"
#include "fat_access.h"
#include "fat_list.h"
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#ifndef SEEK_END
#define SEEK_END 2
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
#ifndef EOF
#define EOF (-1)
#endif
//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
struct
sFL_FILE
;
struct
cluster_lookup
{
uint32
ClusterIdx
;
uint32
CurrentCluster
;
};
typedef
struct
sFL_FILE
{
uint32
parentcluster
;
uint32
startcluster
;
uint32
bytenum
;
uint32
filelength
;
int
filelength_changed
;
char
path
[
FATFS_MAX_LONG_FILENAME
];
char
filename
[
FATFS_MAX_LONG_FILENAME
];
uint8
shortfilename
[
11
];
#ifdef FAT_CLUSTER_CACHE_ENTRIES
uint32
cluster_cache_idx
[
FAT_CLUSTER_CACHE_ENTRIES
];
uint32
cluster_cache_data
[
FAT_CLUSTER_CACHE_ENTRIES
];
#endif
// Cluster Lookup
struct
cluster_lookup
last_fat_lookup
;
// Read/Write sector buffer
uint8
file_data_sector
[
FAT_SECTOR_SIZE
];
uint32
file_data_address
;
int
file_data_dirty
;
// File fopen flags
uint8
flags
;
#define FILE_READ (1 << 0)
#define FILE_WRITE (1 << 1)
#define FILE_APPEND (1 << 2)
#define FILE_BINARY (1 << 3)
#define FILE_ERASE (1 << 4)
#define FILE_CREATE (1 << 5)
struct
fat_node
list_node
;
}
FL_FILE
;
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
// External
void
fl_init
(
void
);
void
fl_attach_locks
(
void
(
*
lock
)(
void
),
void
(
*
unlock
)(
void
));
int
fl_attach_media
(
fn_diskio_read
rd
,
fn_diskio_write
wr
);
void
fl_shutdown
(
void
);
// Standard API
void
*
fl_fopen
(
const
char
*
path
,
const
char
*
modifiers
);
void
fl_fclose
(
void
*
file
);
int
fl_fflush
(
void
*
file
);
int
fl_fgetc
(
void
*
file
);
char
*
fl_fgets
(
char
*
s
,
int
n
,
void
*
f
);
int
fl_fputc
(
int
c
,
void
*
file
);
int
fl_fputs
(
const
char
*
str
,
void
*
file
);
int
fl_fwrite
(
const
void
*
data
,
int
size
,
int
count
,
void
*
file
);
int
fl_fread
(
void
*
data
,
int
size
,
int
count
,
void
*
file
);
int
fl_fseek
(
void
*
file
,
long
offset
,
int
origin
);
int
fl_fgetpos
(
void
*
file
,
uint32
*
position
);
long
fl_ftell
(
void
*
f
);
int
fl_feof
(
void
*
f
);
int
fl_remove
(
const
char
*
filename
);
// Equivelant dirent.h
typedef
struct
fs_dir_list_status
FL_DIR
;
typedef
struct
fs_dir_ent
fl_dirent
;
FL_DIR
*
fl_opendir
(
const
char
*
path
,
FL_DIR
*
dir
);
int
fl_readdir
(
FL_DIR
*
dirls
,
fl_dirent
*
entry
);
int
fl_closedir
(
FL_DIR
*
dir
);
// Extensions
void
fl_listdirectory
(
const
char
*
path
);
int
fl_createdirectory
(
const
char
*
path
);
int
fl_is_dir
(
const
char
*
path
);
int
fl_format
(
uint32
volume_sectors
,
const
char
*
name
);
// Test hooks
#ifdef FATFS_INC_TEST_HOOKS
struct
fatfs
*
fl_get_fs
(
void
);
#endif
//-----------------------------------------------------------------------------
// Stdio file I/O names
//-----------------------------------------------------------------------------
#ifdef USE_FILELIB_STDIO_COMPAT_NAMES
#define FILE FL_FILE
#define fopen(a,b) fl_fopen(a, b)
#define fclose(a) fl_fclose(a)
#define fflush(a) fl_fflush(a)
#define fgetc(a) fl_fgetc(a)
#define fgets(a,b,c) fl_fgets(a, b, c)
#define fputc(a,b) fl_fputc(a, b)
#define fputs(a,b) fl_fputs(a, b)
#define fwrite(a,b,c,d) fl_fwrite(a, b, c, d)
#define fread(a,b,c,d) fl_fread(a, b, c, d)
#define fseek(a,b,c) fl_fseek(a, b, c)
#define fgetpos(a,b) fl_fgetpos(a, b)
#define ftell(a) fl_ftell(a)
#define feof(a) fl_feof(a)
#define remove(a) fl_remove(a)
#define mkdir(a) fl_createdirectory(a)
#define rmdir(a) 0
#endif
#endif
Plugson/src/Lib/fat_io_lib/fat_format.c
0 → 100644
View file @
4bf43ab9
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// FAT File IO Library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <string.h>
#include "fat_defs.h"
#include "fat_access.h"
#include "fat_table.h"
#include "fat_write.h"
#include "fat_string.h"
#include "fat_misc.h"
#include "fat_format.h"
#if FATFS_INC_FORMAT_SUPPORT
//-----------------------------------------------------------------------------
// Tables
//-----------------------------------------------------------------------------
struct
sec_per_clus_table
{
uint32
sectors
;
uint8
sectors_per_cluster
;
};
struct
sec_per_clus_table
_cluster_size_table16
[]
=
{
{
32680
,
2
},
// 16MB - 1K
{
262144
,
4
},
// 128MB - 2K
{
524288
,
8
},
// 256MB - 4K
{
1048576
,
16
},
// 512MB - 8K
{
2097152
,
32
},
// 1GB - 16K
{
4194304
,
64
},
// 2GB - 32K
{
8388608
,
128
},
// 2GB - 64K [Warning only supported by Windows XP onwards]
{
0
,
0
}
// Invalid
};
struct
sec_per_clus_table
_cluster_size_table32
[]
=
{
{
532480
,
1
},
// 260MB - 512b
{
16777216
,
8
},
// 8GB - 4K
{
33554432
,
16
},
// 16GB - 8K
{
67108864
,
32
},
// 32GB - 16K
{
0xFFFFFFFF
,
64
},
// >32GB - 32K
{
0
,
0
}
// Invalid
};
//-----------------------------------------------------------------------------
// fatfs_calc_cluster_size: Calculate what cluster size should be used
//-----------------------------------------------------------------------------
static
uint8
fatfs_calc_cluster_size
(
uint32
sectors
,
int
is_fat32
)
{
int
i
;
if
(
!
is_fat32
)
{
for
(
i
=
0
;
_cluster_size_table16
[
i
].
sectors_per_cluster
!=
0
;
i
++
)
if
(
sectors
<=
_cluster_size_table16
[
i
].
sectors
)
return
_cluster_size_table16
[
i
].
sectors_per_cluster
;
}
else
{
for
(
i
=
0
;
_cluster_size_table32
[
i
].
sectors_per_cluster
!=
0
;
i
++
)
if
(
sectors
<=
_cluster_size_table32
[
i
].
sectors
)
return
_cluster_size_table32
[
i
].
sectors_per_cluster
;
}
return
0
;
}
//-----------------------------------------------------------------------------
// fatfs_erase_sectors: Erase a number of sectors
//-----------------------------------------------------------------------------
static
int
fatfs_erase_sectors
(
struct
fatfs
*
fs
,
uint32
lba
,
int
count
)
{
int
i
;
// Zero sector first
memset
(
fs
->
currentsector
.
sector
,
0
,
FAT_SECTOR_SIZE
);
for
(
i
=
0
;
i
<
count
;
i
++
)
if
(
!
fs
->
disk_io
.
write_media
(
lba
+
i
,
fs
->
currentsector
.
sector
,
1
))
return
0
;
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_create_boot_sector: Create the boot sector
//-----------------------------------------------------------------------------
static
int
fatfs_create_boot_sector
(
struct
fatfs
*
fs
,
uint32
boot_sector_lba
,
uint32
vol_sectors
,
const
char
*
name
,
int
is_fat32
)
{
uint32
total_clusters
;
int
i
;
// Zero sector initially
memset
(
fs
->
currentsector
.
sector
,
0
,
FAT_SECTOR_SIZE
);
// OEM Name & Jump Code
fs
->
currentsector
.
sector
[
0
]
=
0xEB
;
fs
->
currentsector
.
sector
[
1
]
=
0x3C
;
fs
->
currentsector
.
sector
[
2
]
=
0x90
;
fs
->
currentsector
.
sector
[
3
]
=
0x4D
;
fs
->
currentsector
.
sector
[
4
]
=
0x53
;
fs
->
currentsector
.
sector
[
5
]
=
0x44
;
fs
->
currentsector
.
sector
[
6
]
=
0x4F
;
fs
->
currentsector
.
sector
[
7
]
=
0x53
;
fs
->
currentsector
.
sector
[
8
]
=
0x35
;
fs
->
currentsector
.
sector
[
9
]
=
0x2E
;
fs
->
currentsector
.
sector
[
10
]
=
0x30
;
// Bytes per sector
fs
->
currentsector
.
sector
[
11
]
=
(
FAT_SECTOR_SIZE
>>
0
)
&
0xFF
;
fs
->
currentsector
.
sector
[
12
]
=
(
FAT_SECTOR_SIZE
>>
8
)
&
0xFF
;
// Get sectors per cluster size for the disk
fs
->
sectors_per_cluster
=
fatfs_calc_cluster_size
(
vol_sectors
,
is_fat32
);
if
(
!
fs
->
sectors_per_cluster
)
return
0
;
// Invalid disk size
// Sectors per cluster
fs
->
currentsector
.
sector
[
13
]
=
fs
->
sectors_per_cluster
;
// Reserved Sectors
if
(
!
is_fat32
)
fs
->
reserved_sectors
=
8
;
else
fs
->
reserved_sectors
=
32
;
fs
->
currentsector
.
sector
[
14
]
=
(
fs
->
reserved_sectors
>>
0
)
&
0xFF
;
fs
->
currentsector
.
sector
[
15
]
=
(
fs
->
reserved_sectors
>>
8
)
&
0xFF
;
// Number of FATS
fs
->
num_of_fats
=
2
;
fs
->
currentsector
.
sector
[
16
]
=
fs
->
num_of_fats
;
// Max entries in root dir (FAT16 only)
if
(
!
is_fat32
)
{
fs
->
root_entry_count
=
512
;
fs
->
currentsector
.
sector
[
17
]
=
(
fs
->
root_entry_count
>>
0
)
&
0xFF
;
fs
->
currentsector
.
sector
[
18
]
=
(
fs
->
root_entry_count
>>
8
)
&
0xFF
;
}
else
{
fs
->
root_entry_count
=
0
;
fs
->
currentsector
.
sector
[
17
]
=
0
;
fs
->
currentsector
.
sector
[
18
]
=
0
;
}
// [FAT16] Total sectors (use FAT32 count instead)
fs
->
currentsector
.
sector
[
19
]
=
0x00
;
fs
->
currentsector
.
sector
[
20
]
=
0x00
;
// Media type
fs
->
currentsector
.
sector
[
21
]
=
0xF8
;
// FAT16 BS Details
if
(
!
is_fat32
)
{
// Count of sectors used by the FAT table (FAT16 only)
total_clusters
=
(
vol_sectors
/
fs
->
sectors_per_cluster
)
+
1
;
fs
->
fat_sectors
=
(
total_clusters
/
(
FAT_SECTOR_SIZE
/
2
))
+
1
;
fs
->
currentsector
.
sector
[
22
]
=
(
uint8
)((
fs
->
fat_sectors
>>
0
)
&
0xFF
);
fs
->
currentsector
.
sector
[
23
]
=
(
uint8
)((
fs
->
fat_sectors
>>
8
)
&
0xFF
);
// Sectors per track
fs
->
currentsector
.
sector
[
24
]
=
0x00
;
fs
->
currentsector
.
sector
[
25
]
=
0x00
;
// Heads
fs
->
currentsector
.
sector
[
26
]
=
0x00
;
fs
->
currentsector
.
sector
[
27
]
=
0x00
;
// Hidden sectors
fs
->
currentsector
.
sector
[
28
]
=
0x20
;
fs
->
currentsector
.
sector
[
29
]
=
0x00
;
fs
->
currentsector
.
sector
[
30
]
=
0x00
;
fs
->
currentsector
.
sector
[
31
]
=
0x00
;
// Total sectors for this volume
fs
->
currentsector
.
sector
[
32
]
=
(
uint8
)((
vol_sectors
>>
0
)
&
0xFF
);
fs
->
currentsector
.
sector
[
33
]
=
(
uint8
)((
vol_sectors
>>
8
)
&
0xFF
);
fs
->
currentsector
.
sector
[
34
]
=
(
uint8
)((
vol_sectors
>>
16
)
&
0xFF
);
fs
->
currentsector
.
sector
[
35
]
=
(
uint8
)((
vol_sectors
>>
24
)
&
0xFF
);
// Drive number
fs
->
currentsector
.
sector
[
36
]
=
0x00
;
// Reserved
fs
->
currentsector
.
sector
[
37
]
=
0x00
;
// Boot signature
fs
->
currentsector
.
sector
[
38
]
=
0x29
;
// Volume ID
fs
->
currentsector
.
sector
[
39
]
=
0x12
;
fs
->
currentsector
.
sector
[
40
]
=
0x34
;
fs
->
currentsector
.
sector
[
41
]
=
0x56
;
fs
->
currentsector
.
sector
[
42
]
=
0x78
;
// Volume name
for
(
i
=
0
;
i
<
11
;
i
++
)
{
if
(
i
<
(
int
)
strlen
(
name
))
fs
->
currentsector
.
sector
[
i
+
43
]
=
name
[
i
];
else
fs
->
currentsector
.
sector
[
i
+
43
]
=
' '
;
}
// File sys type
fs
->
currentsector
.
sector
[
54
]
=
'F'
;
fs
->
currentsector
.
sector
[
55
]
=
'A'
;
fs
->
currentsector
.
sector
[
56
]
=
'T'
;
fs
->
currentsector
.
sector
[
57
]
=
'1'
;
fs
->
currentsector
.
sector
[
58
]
=
'6'
;
fs
->
currentsector
.
sector
[
59
]
=
' '
;
fs
->
currentsector
.
sector
[
60
]
=
' '
;
fs
->
currentsector
.
sector
[
61
]
=
' '
;
// Signature
fs
->
currentsector
.
sector
[
510
]
=
0x55
;
fs
->
currentsector
.
sector
[
511
]
=
0xAA
;
}
// FAT32 BS Details
else
{
// Count of sectors used by the FAT table (FAT16 only)
fs
->
currentsector
.
sector
[
22
]
=
0
;
fs
->
currentsector
.
sector
[
23
]
=
0
;
// Sectors per track (default)
fs
->
currentsector
.
sector
[
24
]
=
0x3F
;
fs
->
currentsector
.
sector
[
25
]
=
0x00
;
// Heads (default)
fs
->
currentsector
.
sector
[
26
]
=
0xFF
;
fs
->
currentsector
.
sector
[
27
]
=
0x00
;
// Hidden sectors
fs
->
currentsector
.
sector
[
28
]
=
0x00
;
fs
->
currentsector
.
sector
[
29
]
=
0x00
;
fs
->
currentsector
.
sector
[
30
]
=
0x00
;
fs
->
currentsector
.
sector
[
31
]
=
0x00
;
// Total sectors for this volume
fs
->
currentsector
.
sector
[
32
]
=
(
uint8
)((
vol_sectors
>>
0
)
&
0xFF
);
fs
->
currentsector
.
sector
[
33
]
=
(
uint8
)((
vol_sectors
>>
8
)
&
0xFF
);
fs
->
currentsector
.
sector
[
34
]
=
(
uint8
)((
vol_sectors
>>
16
)
&
0xFF
);
fs
->
currentsector
.
sector
[
35
]
=
(
uint8
)((
vol_sectors
>>
24
)
&
0xFF
);
total_clusters
=
(
vol_sectors
/
fs
->
sectors_per_cluster
)
+
1
;
fs
->
fat_sectors
=
(
total_clusters
/
(
FAT_SECTOR_SIZE
/
4
))
+
1
;
// BPB_FATSz32
fs
->
currentsector
.
sector
[
36
]
=
(
uint8
)((
fs
->
fat_sectors
>>
0
)
&
0xFF
);
fs
->
currentsector
.
sector
[
37
]
=
(
uint8
)((
fs
->
fat_sectors
>>
8
)
&
0xFF
);
fs
->
currentsector
.
sector
[
38
]
=
(
uint8
)((
fs
->
fat_sectors
>>
16
)
&
0xFF
);
fs
->
currentsector
.
sector
[
39
]
=
(
uint8
)((
fs
->
fat_sectors
>>
24
)
&
0xFF
);
// BPB_ExtFlags
fs
->
currentsector
.
sector
[
40
]
=
0
;
fs
->
currentsector
.
sector
[
41
]
=
0
;
// BPB_FSVer
fs
->
currentsector
.
sector
[
42
]
=
0
;
fs
->
currentsector
.
sector
[
43
]
=
0
;
// BPB_RootClus
fs
->
currentsector
.
sector
[
44
]
=
(
uint8
)((
fs
->
rootdir_first_cluster
>>
0
)
&
0xFF
);
fs
->
currentsector
.
sector
[
45
]
=
(
uint8
)((
fs
->
rootdir_first_cluster
>>
8
)
&
0xFF
);
fs
->
currentsector
.
sector
[
46
]
=
(
uint8
)((
fs
->
rootdir_first_cluster
>>
16
)
&
0xFF
);
fs
->
currentsector
.
sector
[
47
]
=
(
uint8
)((
fs
->
rootdir_first_cluster
>>
24
)
&
0xFF
);
// BPB_FSInfo
fs
->
currentsector
.
sector
[
48
]
=
(
uint8
)((
fs
->
fs_info_sector
>>
0
)
&
0xFF
);
fs
->
currentsector
.
sector
[
49
]
=
(
uint8
)((
fs
->
fs_info_sector
>>
8
)
&
0xFF
);
// BPB_BkBootSec
fs
->
currentsector
.
sector
[
50
]
=
6
;
fs
->
currentsector
.
sector
[
51
]
=
0
;
// Drive number
fs
->
currentsector
.
sector
[
64
]
=
0x00
;
// Boot signature
fs
->
currentsector
.
sector
[
66
]
=
0x29
;
// Volume ID
fs
->
currentsector
.
sector
[
67
]
=
0x12
;
fs
->
currentsector
.
sector
[
68
]
=
0x34
;
fs
->
currentsector
.
sector
[
69
]
=
0x56
;
fs
->
currentsector
.
sector
[
70
]
=
0x78
;
// Volume name
for
(
i
=
0
;
i
<
11
;
i
++
)
{
if
(
i
<
(
int
)
strlen
(
name
))
fs
->
currentsector
.
sector
[
i
+
71
]
=
name
[
i
];
else
fs
->
currentsector
.
sector
[
i
+
71
]
=
' '
;
}
// File sys type
fs
->
currentsector
.
sector
[
82
]
=
'F'
;
fs
->
currentsector
.
sector
[
83
]
=
'A'
;
fs
->
currentsector
.
sector
[
84
]
=
'T'
;
fs
->
currentsector
.
sector
[
85
]
=
'3'
;
fs
->
currentsector
.
sector
[
86
]
=
'2'
;
fs
->
currentsector
.
sector
[
87
]
=
' '
;
fs
->
currentsector
.
sector
[
88
]
=
' '
;
fs
->
currentsector
.
sector
[
89
]
=
' '
;
// Signature
fs
->
currentsector
.
sector
[
510
]
=
0x55
;
fs
->
currentsector
.
sector
[
511
]
=
0xAA
;
}
if
(
fs
->
disk_io
.
write_media
(
boot_sector_lba
,
fs
->
currentsector
.
sector
,
1
))
return
1
;
else
return
0
;
}
//-----------------------------------------------------------------------------
// fatfs_create_fsinfo_sector: Create the FSInfo sector (FAT32)
//-----------------------------------------------------------------------------
static
int
fatfs_create_fsinfo_sector
(
struct
fatfs
*
fs
,
uint32
sector_lba
)
{
// Zero sector initially
memset
(
fs
->
currentsector
.
sector
,
0
,
FAT_SECTOR_SIZE
);
// FSI_LeadSig
fs
->
currentsector
.
sector
[
0
]
=
0x52
;
fs
->
currentsector
.
sector
[
1
]
=
0x52
;
fs
->
currentsector
.
sector
[
2
]
=
0x61
;
fs
->
currentsector
.
sector
[
3
]
=
0x41
;
// FSI_StrucSig
fs
->
currentsector
.
sector
[
484
]
=
0x72
;
fs
->
currentsector
.
sector
[
485
]
=
0x72
;
fs
->
currentsector
.
sector
[
486
]
=
0x41
;
fs
->
currentsector
.
sector
[
487
]
=
0x61
;
// FSI_Free_Count
fs
->
currentsector
.
sector
[
488
]
=
0xFF
;
fs
->
currentsector
.
sector
[
489
]
=
0xFF
;
fs
->
currentsector
.
sector
[
490
]
=
0xFF
;
fs
->
currentsector
.
sector
[
491
]
=
0xFF
;
// FSI_Nxt_Free
fs
->
currentsector
.
sector
[
492
]
=
0xFF
;
fs
->
currentsector
.
sector
[
493
]
=
0xFF
;
fs
->
currentsector
.
sector
[
494
]
=
0xFF
;
fs
->
currentsector
.
sector
[
495
]
=
0xFF
;
// Signature
fs
->
currentsector
.
sector
[
510
]
=
0x55
;
fs
->
currentsector
.
sector
[
511
]
=
0xAA
;
if
(
fs
->
disk_io
.
write_media
(
sector_lba
,
fs
->
currentsector
.
sector
,
1
))
return
1
;
else
return
0
;
}
//-----------------------------------------------------------------------------
// fatfs_erase_fat: Erase FAT table using fs details in fs struct
//-----------------------------------------------------------------------------
static
int
fatfs_erase_fat
(
struct
fatfs
*
fs
,
int
is_fat32
)
{
uint32
i
;
// Zero sector initially
memset
(
fs
->
currentsector
.
sector
,
0
,
FAT_SECTOR_SIZE
);
// Initialise default allocate / reserved clusters
if
(
!
is_fat32
)
{
SET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
0
,
0xFFF8
);
SET_16BIT_WORD
(
fs
->
currentsector
.
sector
,
2
,
0xFFFF
);
}
else
{
SET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
0
,
0x0FFFFFF8
);
SET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
4
,
0xFFFFFFFF
);
SET_32BIT_WORD
(
fs
->
currentsector
.
sector
,
8
,
0x0FFFFFFF
);
}
if
(
!
fs
->
disk_io
.
write_media
(
fs
->
fat_begin_lba
+
0
,
fs
->
currentsector
.
sector
,
1
))
return
0
;
// Zero remaining FAT sectors
memset
(
fs
->
currentsector
.
sector
,
0
,
FAT_SECTOR_SIZE
);
for
(
i
=
1
;
i
<
fs
->
fat_sectors
*
fs
->
num_of_fats
;
i
++
)
if
(
!
fs
->
disk_io
.
write_media
(
fs
->
fat_begin_lba
+
i
,
fs
->
currentsector
.
sector
,
1
))
return
0
;
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_format_fat16: Format a FAT16 partition
//-----------------------------------------------------------------------------
int
fatfs_format_fat16
(
struct
fatfs
*
fs
,
uint32
volume_sectors
,
const
char
*
name
)
{
fs
->
currentsector
.
address
=
FAT32_INVALID_CLUSTER
;
fs
->
currentsector
.
dirty
=
0
;
fs
->
next_free_cluster
=
0
;
// Invalid
fatfs_fat_init
(
fs
);
// Make sure we have read + write functions
if
(
!
fs
->
disk_io
.
read_media
||
!
fs
->
disk_io
.
write_media
)
return
FAT_INIT_MEDIA_ACCESS_ERROR
;
// Volume is FAT16
fs
->
fat_type
=
FAT_TYPE_16
;
// Not valid for FAT16
fs
->
fs_info_sector
=
0
;
fs
->
rootdir_first_cluster
=
0
;
// Sector 0: Boot sector
// NOTE: We don't need an MBR, it is a waste of a good sector!
fs
->
lba_begin
=
0
;
if
(
!
fatfs_create_boot_sector
(
fs
,
fs
->
lba_begin
,
volume_sectors
,
name
,
0
))
return
0
;
// For FAT16 (which this may be), rootdir_first_cluster is actuall rootdir_first_sector
fs
->
rootdir_first_sector
=
fs
->
reserved_sectors
+
(
fs
->
num_of_fats
*
fs
->
fat_sectors
);
fs
->
rootdir_sectors
=
((
fs
->
root_entry_count
*
32
)
+
(
FAT_SECTOR_SIZE
-
1
))
/
FAT_SECTOR_SIZE
;
// First FAT LBA address
fs
->
fat_begin_lba
=
fs
->
lba_begin
+
fs
->
reserved_sectors
;
// The address of the first data cluster on this volume
fs
->
cluster_begin_lba
=
fs
->
fat_begin_lba
+
(
fs
->
num_of_fats
*
fs
->
fat_sectors
);
// Initialise FAT sectors
if
(
!
fatfs_erase_fat
(
fs
,
0
))
return
0
;
// Erase Root directory
if
(
!
fatfs_erase_sectors
(
fs
,
fs
->
lba_begin
+
fs
->
rootdir_first_sector
,
fs
->
rootdir_sectors
))
return
0
;
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_format_fat32: Format a FAT32 partition
//-----------------------------------------------------------------------------
int
fatfs_format_fat32
(
struct
fatfs
*
fs
,
uint32
volume_sectors
,
const
char
*
name
)
{
fs
->
currentsector
.
address
=
FAT32_INVALID_CLUSTER
;
fs
->
currentsector
.
dirty
=
0
;
fs
->
next_free_cluster
=
0
;
// Invalid
fatfs_fat_init
(
fs
);
// Make sure we have read + write functions
if
(
!
fs
->
disk_io
.
read_media
||
!
fs
->
disk_io
.
write_media
)
return
FAT_INIT_MEDIA_ACCESS_ERROR
;
// Volume is FAT32
fs
->
fat_type
=
FAT_TYPE_32
;
// Basic defaults for normal FAT32 partitions
fs
->
fs_info_sector
=
1
;
fs
->
rootdir_first_cluster
=
2
;
// Sector 0: Boot sector
// NOTE: We don't need an MBR, it is a waste of a good sector!
fs
->
lba_begin
=
0
;
if
(
!
fatfs_create_boot_sector
(
fs
,
fs
->
lba_begin
,
volume_sectors
,
name
,
1
))
return
0
;
// First FAT LBA address
fs
->
fat_begin_lba
=
fs
->
lba_begin
+
fs
->
reserved_sectors
;
// The address of the first data cluster on this volume
fs
->
cluster_begin_lba
=
fs
->
fat_begin_lba
+
(
fs
->
num_of_fats
*
fs
->
fat_sectors
);
// Initialise FSInfo sector
if
(
!
fatfs_create_fsinfo_sector
(
fs
,
fs
->
fs_info_sector
))
return
0
;
// Initialise FAT sectors
if
(
!
fatfs_erase_fat
(
fs
,
1
))
return
0
;
// Erase Root directory
if
(
!
fatfs_erase_sectors
(
fs
,
fatfs_lba_of_cluster
(
fs
,
fs
->
rootdir_first_cluster
),
fs
->
sectors_per_cluster
))
return
0
;
return
1
;
}
//-----------------------------------------------------------------------------
// fatfs_format: Format a partition with either FAT16 or FAT32 based on size
//-----------------------------------------------------------------------------
int
fatfs_format
(
struct
fatfs
*
fs
,
uint32
volume_sectors
,
const
char
*
name
)
{
// 2GB - 32K limit for safe behaviour for FAT16
if
(
volume_sectors
<=
4194304
)
return
fatfs_format_fat16
(
fs
,
volume_sectors
,
name
);
else
return
fatfs_format_fat32
(
fs
,
volume_sectors
,
name
);
}
#endif
/*FATFS_INC_FORMAT_SUPPORT*/
Plugson/src/Lib/fat_io_lib/fat_format.h
0 → 100644
View file @
4bf43ab9
#ifndef __FAT_FORMAT_H__
#define __FAT_FORMAT_H__
#include "fat_defs.h"
#include "fat_opts.h"
#include "fat_access.h"
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
int
fatfs_format
(
struct
fatfs
*
fs
,
uint32
volume_sectors
,
const
char
*
name
);
int
fatfs_format_fat16
(
struct
fatfs
*
fs
,
uint32
volume_sectors
,
const
char
*
name
);
int
fatfs_format_fat32
(
struct
fatfs
*
fs
,
uint32
volume_sectors
,
const
char
*
name
);
#endif
Plugson/src/Lib/fat_io_lib/fat_list.h
0 → 100644
View file @
4bf43ab9
#ifndef __FAT_LIST_H__
#define __FAT_LIST_H__
#ifndef FAT_ASSERT
#define FAT_ASSERT(x)
#endif
#ifndef FAT_INLINE
#define FAT_INLINE
#endif
//-----------------------------------------------------------------
// Types
//-----------------------------------------------------------------
struct
fat_list
;
struct
fat_node
{
struct
fat_node
*
previous
;
struct
fat_node
*
next
;
};
struct
fat_list
{
struct
fat_node
*
head
;
struct
fat_node
*
tail
;
};
//-----------------------------------------------------------------
// Macros
//-----------------------------------------------------------------
#define fat_list_entry(p, t, m) p ? ((t *)((char *)(p)-(char*)(&((t *)0)->m))) : 0
#define fat_list_next(l, p) (p)->next
#define fat_list_prev(l, p) (p)->previous
#define fat_list_first(l) (l)->head
#define fat_list_last(l) (l)->tail
#define fat_list_for_each(l, p) for ((p) = (l)->head; (p); (p) = (p)->next)
//-----------------------------------------------------------------
// Inline Functions
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// fat_list_init:
//-----------------------------------------------------------------
static
FAT_INLINE
void
fat_list_init
(
struct
fat_list
*
list
)
{
FAT_ASSERT
(
list
);
list
->
head
=
list
->
tail
=
0
;
}
//-----------------------------------------------------------------
// fat_list_remove:
//-----------------------------------------------------------------
static
FAT_INLINE
void
fat_list_remove
(
struct
fat_list
*
list
,
struct
fat_node
*
node
)
{
FAT_ASSERT
(
list
);
FAT_ASSERT
(
node
);
if
(
!
node
->
previous
)
list
->
head
=
node
->
next
;
else
node
->
previous
->
next
=
node
->
next
;
if
(
!
node
->
next
)
list
->
tail
=
node
->
previous
;
else
node
->
next
->
previous
=
node
->
previous
;
}
//-----------------------------------------------------------------
// fat_list_insert_after:
//-----------------------------------------------------------------
static
FAT_INLINE
void
fat_list_insert_after
(
struct
fat_list
*
list
,
struct
fat_node
*
node
,
struct
fat_node
*
new_node
)
{
FAT_ASSERT
(
list
);
FAT_ASSERT
(
node
);
FAT_ASSERT
(
new_node
);
new_node
->
previous
=
node
;
new_node
->
next
=
node
->
next
;
if
(
!
node
->
next
)
list
->
tail
=
new_node
;
else
node
->
next
->
previous
=
new_node
;
node
->
next
=
new_node
;
}
//-----------------------------------------------------------------
// fat_list_insert_before:
//-----------------------------------------------------------------
static
FAT_INLINE
void
fat_list_insert_before
(
struct
fat_list
*
list
,
struct
fat_node
*
node
,
struct
fat_node
*
new_node
)
{
FAT_ASSERT
(
list
);
FAT_ASSERT
(
node
);
FAT_ASSERT
(
new_node
);
new_node
->
previous
=
node
->
previous
;
new_node
->
next
=
node
;
if
(
!
node
->
previous
)
list
->
head
=
new_node
;
else
node
->
previous
->
next
=
new_node
;
node
->
previous
=
new_node
;
}
//-----------------------------------------------------------------
// fat_list_insert_first:
//-----------------------------------------------------------------
static
FAT_INLINE
void
fat_list_insert_first
(
struct
fat_list
*
list
,
struct
fat_node
*
node
)
{
FAT_ASSERT
(
list
);
FAT_ASSERT
(
node
);
if
(
!
list
->
head
)
{
list
->
head
=
node
;
list
->
tail
=
node
;
node
->
previous
=
0
;
node
->
next
=
0
;
}
else
fat_list_insert_before
(
list
,
list
->
head
,
node
);
}
//-----------------------------------------------------------------
// fat_list_insert_last:
//-----------------------------------------------------------------
static
FAT_INLINE
void
fat_list_insert_last
(
struct
fat_list
*
list
,
struct
fat_node
*
node
)
{
FAT_ASSERT
(
list
);
FAT_ASSERT
(
node
);
if
(
!
list
->
tail
)
fat_list_insert_first
(
list
,
node
);
else
fat_list_insert_after
(
list
,
list
->
tail
,
node
);
}
//-----------------------------------------------------------------
// fat_list_is_empty:
//-----------------------------------------------------------------
static
FAT_INLINE
int
fat_list_is_empty
(
struct
fat_list
*
list
)
{
FAT_ASSERT
(
list
);
return
!
list
->
head
;
}
//-----------------------------------------------------------------
// fat_list_pop_head:
//-----------------------------------------------------------------
static
FAT_INLINE
struct
fat_node
*
fat_list_pop_head
(
struct
fat_list
*
list
)
{
struct
fat_node
*
node
;
FAT_ASSERT
(
list
);
node
=
fat_list_first
(
list
);
if
(
node
)
fat_list_remove
(
list
,
node
);
return
node
;
}
#endif
Prev
1
2
3
4
5
6
7
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment