mirror of
https://github.com/ventoy/Ventoy.git
synced 2025-09-16 09:01:15 +00:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b5a649f96f | ||
|
443a1344f2 | ||
|
d3de1a91f8 | ||
|
580ad598f6 | ||
|
0891e34d47 | ||
|
4d777090cb | ||
|
b0568922d2 | ||
|
69b6bb8fca | ||
|
3d686c27d7 | ||
|
90ba217ec7 | ||
|
fab070ef64 |
2
.github/ISSUE_TEMPLATE/issue_template.yml
vendored
2
.github/ISSUE_TEMPLATE/issue_template.yml
vendored
@@ -21,7 +21,7 @@ body:
|
||||
attributes:
|
||||
label: Ventoy Version
|
||||
description: What version of ventoy are you running?
|
||||
placeholder: 1.0.59
|
||||
placeholder: 1.0.61
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
@@ -405,7 +405,9 @@ const char * g_ventoy_tip_msg2 = NULL;
|
||||
static const char *g_ventoy_cur_img_path = NULL;
|
||||
static void menu_set_chosen_tip(grub_menu_t menu, int entry)
|
||||
{
|
||||
int i;
|
||||
img_info *img;
|
||||
menu_tip *tip;
|
||||
grub_menu_entry_t e = grub_menu_get_entry (menu, entry);
|
||||
|
||||
g_ventoy_tip_msg1 = g_ventoy_tip_msg2 = NULL;
|
||||
@@ -419,6 +421,26 @@ static void menu_set_chosen_tip(grub_menu_t menu, int entry)
|
||||
g_ventoy_cur_img_path = img->path;
|
||||
}
|
||||
}
|
||||
else if (e && e->id && grub_strncmp(e->id, "DIR_", 4) == 0)
|
||||
{
|
||||
for (i = 0; i < e->argc; i++)
|
||||
{
|
||||
if (e->args[i] && grub_strncmp(e->args[i], "_VTIP_", 6) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < e->argc)
|
||||
{
|
||||
tip = (menu_tip *)(void *)grub_strtoul(e->args[i] + 6, NULL, 16);
|
||||
if (tip)
|
||||
{
|
||||
g_ventoy_tip_msg1 = tip->tip1;
|
||||
g_ventoy_tip_msg2 = tip->tip2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -1866,7 +1866,7 @@ static int ventoy_collect_img_files(const char *filename, const struct grub_dirh
|
||||
|
||||
img->alias = ventoy_plugin_get_menu_alias(vtoy_alias_image_file, img->path);
|
||||
|
||||
tip = ventoy_plugin_get_menu_tip(img->path);
|
||||
tip = ventoy_plugin_get_menu_tip(vtoy_tip_image_file, img->path);
|
||||
if (tip)
|
||||
{
|
||||
img->tip1 = tip->tip1;
|
||||
@@ -2067,7 +2067,8 @@ static int ventoy_dynamic_tree_menu(img_iterator_node *node)
|
||||
const char *dir_class = NULL;
|
||||
const char *dir_alias = NULL;
|
||||
img_iterator_node *child = NULL;
|
||||
|
||||
const menu_tip *tip = NULL;
|
||||
|
||||
if (node->isocnt == 0 || node->done == 1)
|
||||
{
|
||||
return 0;
|
||||
@@ -2107,20 +2108,22 @@ static int ventoy_dynamic_tree_menu(img_iterator_node *node)
|
||||
dir_class = "vtoydir";
|
||||
}
|
||||
|
||||
tip = ventoy_plugin_get_menu_tip(vtoy_tip_directory, node->dir);
|
||||
|
||||
dir_alias = ventoy_plugin_get_menu_alias(vtoy_alias_directory, node->dir);
|
||||
if (dir_alias)
|
||||
{
|
||||
if (g_tree_view_menu_style == 0)
|
||||
{
|
||||
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
|
||||
"submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
|
||||
"DIR", dir_alias, dir_class, node->dir + offset);
|
||||
"submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
|
||||
"DIR", dir_alias, dir_class, node->dir + offset, tip);
|
||||
}
|
||||
else
|
||||
{
|
||||
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
|
||||
"submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
|
||||
dir_alias, dir_class, node->dir + offset);
|
||||
"submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
|
||||
dir_alias, dir_class, node->dir + offset, tip);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2130,14 +2133,14 @@ static int ventoy_dynamic_tree_menu(img_iterator_node *node)
|
||||
if (g_tree_view_menu_style == 0)
|
||||
{
|
||||
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
|
||||
"submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
|
||||
"DIR", dir_alias, dir_class, node->dir + offset);
|
||||
"submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
|
||||
"DIR", dir_alias, dir_class, node->dir + offset, tip);
|
||||
}
|
||||
else
|
||||
{
|
||||
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
|
||||
"submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
|
||||
dir_alias, dir_class, node->dir + offset);
|
||||
"submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
|
||||
dir_alias, dir_class, node->dir + offset, tip);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -896,8 +896,11 @@ typedef struct menu_alias
|
||||
struct menu_alias *next;
|
||||
}menu_alias;
|
||||
|
||||
#define vtoy_tip_image_file 0
|
||||
#define vtoy_tip_directory 1
|
||||
typedef struct menu_tip
|
||||
{
|
||||
int type;
|
||||
int pathlen;
|
||||
char isopath[256];
|
||||
char tip1[1024];
|
||||
@@ -1063,7 +1066,7 @@ int ventoy_fill_windows_rtdata(void *buf, char *isopath);
|
||||
int ventoy_plugin_get_persistent_chunklist(const char *isopath, int index, ventoy_img_chunk_list *chunk_list);
|
||||
const char * ventoy_plugin_get_injection(const char *isopath);
|
||||
const char * ventoy_plugin_get_menu_alias(int type, const char *isopath);
|
||||
const menu_tip * ventoy_plugin_get_menu_tip(const char *isopath);
|
||||
const menu_tip * ventoy_plugin_get_menu_tip(int type, const char *isopath);
|
||||
const char * ventoy_plugin_get_menu_class(int type, const char *name, const char *path);
|
||||
int ventoy_plugin_check_memdisk(const char *isopath);
|
||||
int ventoy_plugin_get_image_list_index(int type, const char *name);
|
||||
|
@@ -1478,6 +1478,7 @@ static int ventoy_plugin_menualias_entry(VTOY_JSON *json, const char *isodisk)
|
||||
|
||||
static int ventoy_plugin_menutip_check(VTOY_JSON *json, const char *isodisk)
|
||||
{
|
||||
int type;
|
||||
const char *path = NULL;
|
||||
const char *tip = NULL;
|
||||
VTOY_JSON *pNode = NULL;
|
||||
@@ -1511,20 +1512,41 @@ static int ventoy_plugin_menutip_check(VTOY_JSON *json, const char *isodisk)
|
||||
pNode = vtoy_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "tips");
|
||||
for (pNode = pNode->pstChild; pNode; pNode = pNode->pstNext)
|
||||
{
|
||||
type = vtoy_tip_image_file;
|
||||
path = vtoy_json_get_string_ex(pNode->pstChild, "image");
|
||||
if (!path)
|
||||
{
|
||||
path = vtoy_json_get_string_ex(pNode->pstChild, "dir");
|
||||
type = vtoy_tip_directory;
|
||||
}
|
||||
|
||||
if (path && path[0] == '/')
|
||||
{
|
||||
if (grub_strchr(path, '*'))
|
||||
if (vtoy_tip_image_file == type)
|
||||
{
|
||||
grub_printf("image: <%s> [ * ]\n", path);
|
||||
}
|
||||
else if (ventoy_check_file_exist("%s%s", isodisk, path))
|
||||
{
|
||||
grub_printf("image: <%s> [ OK ]\n", path);
|
||||
if (grub_strchr(path, '*'))
|
||||
{
|
||||
grub_printf("image: <%s> [ * ]\n", path);
|
||||
}
|
||||
else if (ventoy_is_file_exist("%s%s", isodisk, path))
|
||||
{
|
||||
grub_printf("image: <%s> [ OK ]\n", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_printf("image: <%s> [ NOT EXIST ]\n", path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_printf("image: <%s> [ NOT EXIST ]\n", path);
|
||||
if (ventoy_is_dir_exist("%s%s", isodisk, path))
|
||||
{
|
||||
grub_printf("dir: <%s> [ OK ]\n", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_printf("dir: <%s> [ NOT EXIST ]\n", path);
|
||||
}
|
||||
}
|
||||
|
||||
tip = vtoy_json_get_string_ex(pNode->pstChild, "tip");
|
||||
@@ -1558,6 +1580,7 @@ static int ventoy_plugin_menutip_check(VTOY_JSON *json, const char *isodisk)
|
||||
|
||||
static int ventoy_plugin_menutip_entry(VTOY_JSON *json, const char *isodisk)
|
||||
{
|
||||
int type;
|
||||
const char *path = NULL;
|
||||
const char *tip = NULL;
|
||||
VTOY_JSON *pNode = NULL;
|
||||
@@ -1610,12 +1633,20 @@ static int ventoy_plugin_menutip_entry(VTOY_JSON *json, const char *isodisk)
|
||||
|
||||
for (pNode = pNode->pstChild; pNode; pNode = pNode->pstNext)
|
||||
{
|
||||
type = vtoy_tip_image_file;
|
||||
path = vtoy_json_get_string_ex(pNode->pstChild, "image");
|
||||
if (!path)
|
||||
{
|
||||
path = vtoy_json_get_string_ex(pNode->pstChild, "dir");
|
||||
type = vtoy_tip_directory;
|
||||
}
|
||||
|
||||
if (path && path[0] == '/')
|
||||
{
|
||||
node = grub_zalloc(sizeof(menu_tip));
|
||||
if (node)
|
||||
{
|
||||
node->type = type;
|
||||
node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", path);
|
||||
|
||||
tip = vtoy_json_get_string_ex(pNode->pstChild, "tip");
|
||||
@@ -2754,7 +2785,7 @@ const char * ventoy_plugin_get_menu_alias(int type, const char *isopath)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const menu_tip * ventoy_plugin_get_menu_tip(const char *isopath)
|
||||
const menu_tip * ventoy_plugin_get_menu_tip(int type, const char *isopath)
|
||||
{
|
||||
int len;
|
||||
menu_tip *node = NULL;
|
||||
@@ -2767,7 +2798,8 @@ const menu_tip * ventoy_plugin_get_menu_tip(const char *isopath)
|
||||
len = (int)grub_strlen(isopath);
|
||||
for (node = g_menu_tip_head; node; node = node->next)
|
||||
{
|
||||
if (node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
|
||||
if (node->type == type && node->pathlen &&
|
||||
node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
Binary file not shown.
@@ -23,6 +23,8 @@ else
|
||||
fi
|
||||
export PATH="./tool/$TOOLDIR:$PATH"
|
||||
|
||||
rm -f ./log.txt
|
||||
|
||||
|
||||
echo ''
|
||||
echo '**********************************************'
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -38,13 +38,10 @@ sh buildedk.sh >> $LOG 2>&1 || exit 1
|
||||
#cd $VTOY_PATH/VtoyTool
|
||||
#sh build.sh || exit 1
|
||||
|
||||
#cd $VTOY_PATH/vtoyfat/fat_io_lib
|
||||
#cd $VTOY_PATH/vtoycli/fat_io_lib
|
||||
#sh buildlib.sh
|
||||
|
||||
#cd $VTOY_PATH/vtoyfat
|
||||
#sh build.sh || exit 1
|
||||
|
||||
#cd $VTOY_PATH/vtoygpt
|
||||
#cd $VTOY_PATH/vtoycli
|
||||
#sh build.sh || exit 1
|
||||
|
||||
#cd $VTOY_PATH/FUSEISO
|
||||
|
@@ -2010,7 +2010,7 @@ function img_unsupport_menuentry {
|
||||
#############################################################
|
||||
#############################################################
|
||||
|
||||
set VENTOY_VERSION="1.0.59"
|
||||
set VENTOY_VERSION="1.0.61"
|
||||
|
||||
#ACPI not compatible with Window7/8, so disable by default
|
||||
set VTOY_PARAM_NO_ACPI=1
|
||||
|
18
INSTALL/grub/help/de_DE.txt
Normal file
18
INSTALL/grub/help/de_DE.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
h - Zeigt dieses Hilfe Menu
|
||||
F1 - Memdisk Modus (Nur für kleine WinPE/LiveCD ISO/IMG)
|
||||
F2 - Neustarten/Herunterfahren
|
||||
F3 - Menu wechsel zwischen Baum <-> Listen Ansicht
|
||||
F4 - Windows/Linux vom lokalem Datenträger starten
|
||||
F5 - Dienstprogramme
|
||||
F6 - Benutzerdefiniertes Grub2-Menü laden
|
||||
F7 - Wechseln zwischen GUI-Modus <-> TEXT-Modus
|
||||
|
||||
m - Prüfsummencheck Image Dateien (md5/sha1/sha256/sha512)
|
||||
Ctrl+w - WIMBOOT Modus (Nur für Standard Windows ISO)
|
||||
Ctrl+r - Grub2 Modus (Nur für einige Linux distros)
|
||||
Ctrl+i - Kompatibilitäts Modus (Nur für Fehleranalyse)
|
||||
Ctrl+u - Lade ISO efi Treiber (Nur für Fehleranalyse, darf nicht offiziel benutzt werden)
|
||||
|
||||
|
||||
|
||||
Drücke ESC für Zurück ......
|
@@ -76,6 +76,11 @@ else
|
||||
terminal_output console
|
||||
chainloader /EFI/Microsoft/Boot/bootmgfw.efi
|
||||
boot
|
||||
elif [ -f ($vtoydev,$partid)/efi/Microsoft/Boot/bootmgfw.efi ]; then
|
||||
set root=($vtoydev,$partid)
|
||||
terminal_output console
|
||||
chainloader /efi/Microsoft/Boot/bootmgfw.efi
|
||||
boot
|
||||
fi
|
||||
else
|
||||
break
|
||||
@@ -87,6 +92,10 @@ else
|
||||
terminal_output console
|
||||
chainloader /EFI/Microsoft/Boot/bootmgfw.efi
|
||||
boot
|
||||
elif search -n -s -f /efi/Microsoft/Boot/bootmgfw.efi; then
|
||||
terminal_output console
|
||||
chainloader /efi/Microsoft/Boot/bootmgfw.efi
|
||||
boot
|
||||
else
|
||||
echo "Windows NOT found ..."
|
||||
fi
|
||||
|
@@ -16,6 +16,7 @@ print_usage() {
|
||||
echo ' -s/-S enable/disable secure boot support (default is disabled)'
|
||||
echo ' -g use GPT partition style, default is MBR (only for install)'
|
||||
echo ' -L Label of the 1st exfat partition (default is Ventoy)'
|
||||
echo ' -n try non-destructive installation (only for install)'
|
||||
echo ''
|
||||
}
|
||||
|
||||
@@ -28,6 +29,8 @@ while [ -n "$1" ]; do
|
||||
elif [ "$1" = "-I" ]; then
|
||||
MODE="install"
|
||||
FORCE="Y"
|
||||
elif [ "$1" = "-n" ]; then
|
||||
NONDESTRUCTIVE="Y"
|
||||
elif [ "$1" = "-u" ]; then
|
||||
MODE="update"
|
||||
elif [ "$1" = "-l" ]; then
|
||||
@@ -162,7 +165,7 @@ if [ -d ./tmp_mnt ]; then
|
||||
fi
|
||||
|
||||
|
||||
if [ "$MODE" = "install" ]; then
|
||||
if [ "$MODE" = "install" -a -z "$NONDESTRUCTIVE" ]; then
|
||||
vtdebug "install Ventoy ..."
|
||||
|
||||
if [ -n "$VTGPT" ]; then
|
||||
@@ -255,7 +258,10 @@ if [ "$MODE" = "install" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! dd if=/dev/zero of=$DISK bs=1 count=512 status=none conv=fsync; then
|
||||
# check and umount
|
||||
check_umount_disk "$DISK"
|
||||
|
||||
if ! dd if=/dev/zero of=$DISK bs=64 count=512 status=none conv=fsync; then
|
||||
vterr "Write data to $DISK failed, please check whether it's in use."
|
||||
exit 1
|
||||
fi
|
||||
@@ -281,10 +287,14 @@ if [ "$MODE" = "install" ]; then
|
||||
PART1=$(get_disk_part_name $DISK 1)
|
||||
PART2=$(get_disk_part_name $DISK 2)
|
||||
|
||||
#clean part2
|
||||
dd status=none conv=fsync if=/dev/zero of=$DISK bs=512 count=32 seek=$part2_start_sector
|
||||
|
||||
#format part1
|
||||
vtinfo "Format partition 1 ..."
|
||||
mkexfatfs -n "$VTNEW_LABEL" -s $cluster_sectors ${PART1}
|
||||
|
||||
vtinfo "writing data to disk ..."
|
||||
|
||||
vtinfo "writing data to disk ..."
|
||||
dd status=none conv=fsync if=./boot/boot.img of=$DISK bs=1 count=446
|
||||
|
||||
if [ -n "$VTGPT" ]; then
|
||||
@@ -314,51 +324,181 @@ if [ "$MODE" = "install" ]; then
|
||||
sync
|
||||
|
||||
vtinfo "esp partition processing ..."
|
||||
|
||||
sleep 1
|
||||
check_umount_disk "$DISK"
|
||||
|
||||
if [ "$SECUREBOOT" != "YES" ]; then
|
||||
mkdir ./tmp_mnt
|
||||
|
||||
vtdebug "mounting part2 ...."
|
||||
for tt in 1 2 3 4 5; do
|
||||
if mount ${PART2} ./tmp_mnt > /dev/null 2>&1; then
|
||||
vtdebug "mounting part2 success"
|
||||
break
|
||||
fi
|
||||
|
||||
check_umount_disk "$DISK"
|
||||
sleep 2
|
||||
done
|
||||
|
||||
rm -f ./tmp_mnt/EFI/BOOT/BOOTX64.EFI
|
||||
rm -f ./tmp_mnt/EFI/BOOT/grubx64.efi
|
||||
rm -f ./tmp_mnt/EFI/BOOT/BOOTIA32.EFI
|
||||
rm -f ./tmp_mnt/EFI/BOOT/grubia32.efi
|
||||
rm -f ./tmp_mnt/EFI/BOOT/MokManager.efi
|
||||
rm -f ./tmp_mnt/EFI/BOOT/mmia32.efi
|
||||
rm -f ./tmp_mnt/ENROLL_THIS_KEY_IN_MOKMANAGER.cer
|
||||
mv ./tmp_mnt/EFI/BOOT/grubx64_real.efi ./tmp_mnt/EFI/BOOT/BOOTX64.EFI
|
||||
mv ./tmp_mnt/EFI/BOOT/grubia32_real.efi ./tmp_mnt/EFI/BOOT/BOOTIA32.EFI
|
||||
|
||||
sync
|
||||
|
||||
for tt in 1 2 3; do
|
||||
if umount ./tmp_mnt; then
|
||||
vtdebug "umount part2 success"
|
||||
rm -rf ./tmp_mnt
|
||||
break
|
||||
else
|
||||
vtdebug "umount part2 failed, now retry..."
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
if [ "$SECUREBOOT" != "YES" ]; then
|
||||
sleep 2
|
||||
check_umount_disk "$DISK"
|
||||
vtoycli partresize -s $DISK $part2_start_sector
|
||||
fi
|
||||
|
||||
echo ""
|
||||
vtinfo "Install Ventoy to $DISK successfully finished."
|
||||
echo ""
|
||||
|
||||
elif [ "$MODE" = "install" -a -n "$NONDESTRUCTIVE" ]; then
|
||||
vtdebug "non-destructive install Ventoy ..."
|
||||
|
||||
version=$(get_disk_ventoy_version $DISK)
|
||||
if [ $? -eq 0 ]; then
|
||||
if [ -z "$FORCE" ]; then
|
||||
vtwarn "$DISK already contains a Ventoy with version $version."
|
||||
vtwarn "You can not do and don not need non-destructive installation."
|
||||
vtwarn ""
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
disk_sector_num=$(cat /sys/block/${DISK#/dev/}/size)
|
||||
disk_size_gb=$(expr $disk_sector_num / 2097152)
|
||||
|
||||
if vtoycli partresize -t $DISK; then
|
||||
OldStyle="GPT"
|
||||
else
|
||||
OldStyle="MBR"
|
||||
fi
|
||||
|
||||
#Print disk info
|
||||
echo "Disk : $DISK"
|
||||
parted -s $DISK p 2>&1 | grep Model
|
||||
echo "Size : $disk_size_gb GB"
|
||||
echo "Style: $OldStyle"
|
||||
echo ''
|
||||
|
||||
vtwarn "Attention:"
|
||||
vtwarn "Ventoy will try non-destructive installation on $DISK if possible."
|
||||
echo ""
|
||||
|
||||
read -p 'Continue? (y/n) ' Answer
|
||||
if [ "$Answer" != "y" ]; then
|
||||
if [ "$Answer" != "Y" ]; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $disk_sector_num -le $VENTOY_SECTOR_NUM ]; then
|
||||
vterr "No enough space in disk $DISK"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PART1=$(get_disk_part_name $DISK 1)
|
||||
PART2=$(get_disk_part_name $DISK 2)
|
||||
|
||||
#Part1 size in MB aligned with 4KB
|
||||
PART1_SECTORS=$(cat /sys/class/block/${PART1#/dev/}/size)
|
||||
PART1_4K=$(expr $PART1_SECTORS / 8)
|
||||
PART1_MB=$(expr $PART1_4K / 256)
|
||||
PART1_NEW_MB=$(expr $PART1_MB - 32)
|
||||
|
||||
echo "$PART1 is ${PART1_MB}MB"
|
||||
|
||||
#check partition layout
|
||||
echo "check partition layout ..."
|
||||
vtoycli partresize -c $DISK
|
||||
vtRet=$?
|
||||
if [ $vtRet -eq 0 ]; then
|
||||
exit 1
|
||||
else
|
||||
# check and umount
|
||||
check_umount_disk "$DISK"
|
||||
sleep 1
|
||||
check_umount_disk "$DISK"
|
||||
|
||||
if [ $vtRet -eq 1 ]; then
|
||||
echo "Free space enough, start install..."
|
||||
part2_start_sector=$(expr $PART1_SECTORS + 2048)
|
||||
elif [ $vtRet -eq 2 ]; then
|
||||
echo "We need to shrink partition 1 firstly ..."
|
||||
|
||||
PART1_BLKID=$(blkid $PART1)
|
||||
blkid $PART1
|
||||
|
||||
if echo $PART1_BLKID | egrep -q -i 'TYPE=ntfs|TYPE=.ntfs'; then
|
||||
echo "Partition 1 contains NTFS filesystem"
|
||||
|
||||
which ntfsresize
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "###[FAIL] ntfsresize not found. Please install ntfs-3g package."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "ntfsfix -b -d $PART1 ..."
|
||||
ntfsfix -b -d $PART1
|
||||
|
||||
echo "ntfsresize --size ${PART1_NEW_MB}Mi $PART1 ..."
|
||||
ntfsresize -f --size ${PART1_NEW_MB}Mi $PART1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "###[FAIL] ntfsresize failed."
|
||||
exit 1
|
||||
fi
|
||||
elif echo $PART1_BLKID | egrep -q -i 'TYPE=ext[2-4]|TYPE=.ext[2-4]'; then
|
||||
echo "Partition 1 contains EXT filesystem"
|
||||
|
||||
which resize2fs
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "###[FAIL] resize2fs not found. Please install e2fsprogs package."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "e2fsck -f $PART1 ..."
|
||||
e2fsck -f $PART1
|
||||
|
||||
echo "resize2fs $PART1 ${PART1_NEW_MB}M ..."
|
||||
resize2fs $PART1 ${PART1_NEW_MB}M
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "###[FAIL] resize2fs failed."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "###[FAIL] Unsupported filesystem in partition 1."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sync
|
||||
PART1_NEW_END_MB=$(expr $PART1_NEW_MB + 1)
|
||||
part2_start_sector=$(expr $PART1_NEW_END_MB \* 2048)
|
||||
fi
|
||||
fi
|
||||
|
||||
vtinfo "writing data to disk part2_start=$part2_start_sector ..."
|
||||
|
||||
dd status=none conv=fsync if=./boot/boot.img of=$DISK bs=1 count=440
|
||||
|
||||
if [ "$OldStyle" = "GPT" ]; then
|
||||
echo -en '\x22' | dd status=none of=$DISK conv=fsync bs=1 count=1 seek=92
|
||||
xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2014 seek=34
|
||||
echo -en '\x23' | dd of=$DISK conv=fsync bs=1 count=1 seek=17908 status=none
|
||||
else
|
||||
xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2047 seek=1
|
||||
fi
|
||||
|
||||
xzcat ./ventoy/ventoy.disk.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=$VENTOY_SECTOR_NUM seek=$part2_start_sector
|
||||
|
||||
#test UUID
|
||||
testUUIDStr=$(vtoy_gen_uuid | hexdump -C)
|
||||
vtdebug "test uuid: $testUUIDStr"
|
||||
|
||||
#disk uuid
|
||||
vtoy_gen_uuid | dd status=none conv=fsync of=${DISK} seek=384 bs=1 count=16
|
||||
|
||||
vtinfo "sync data ..."
|
||||
sync
|
||||
|
||||
vtinfo "esp partition processing ..."
|
||||
if [ "$SECUREBOOT" != "YES" ]; then
|
||||
vtoycli partresize -s $DISK $part2_start_sector
|
||||
fi
|
||||
|
||||
vtinfo "update partition table $DISK $part2_start_sector ..."
|
||||
vtoycli partresize -p $DISK $part2_start_sector
|
||||
if [ $? -eq 0 ]; then
|
||||
sync
|
||||
echo ""
|
||||
vtinfo "Ventoy non-destructive installation on $DISK successfully finished."
|
||||
echo ""
|
||||
else
|
||||
echo ""
|
||||
vterr "Ventoy non-destructive installation on $DISK failed."
|
||||
echo ""
|
||||
fi
|
||||
|
||||
else
|
||||
vtdebug "update Ventoy ..."
|
||||
@@ -441,47 +581,13 @@ else
|
||||
check_umount_disk "$DISK"
|
||||
|
||||
xzcat ./ventoy/ventoy.disk.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=$VENTOY_SECTOR_NUM seek=$part2_start
|
||||
|
||||
sync
|
||||
|
||||
vtinfo "esp partition processing ..."
|
||||
if [ "$SECUREBOOT" != "YES" ]; then
|
||||
mkdir ./tmp_mnt
|
||||
|
||||
vtdebug "mounting part2 ...."
|
||||
for tt in 1 2 3 4 5; do
|
||||
check_umount_disk "$DISK"
|
||||
|
||||
if mount ${PART2} ./tmp_mnt > /dev/null 2>&1; then
|
||||
vtdebug "mounting part2 success"
|
||||
break
|
||||
else
|
||||
vtdebug "mounting part2 failed, now wait and retry..."
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
rm -f ./tmp_mnt/EFI/BOOT/BOOTX64.EFI
|
||||
rm -f ./tmp_mnt/EFI/BOOT/grubx64.efi
|
||||
rm -f ./tmp_mnt/EFI/BOOT/BOOTIA32.EFI
|
||||
rm -f ./tmp_mnt/EFI/BOOT/grubia32.efi
|
||||
rm -f ./tmp_mnt/EFI/BOOT/MokManager.efi
|
||||
rm -f ./tmp_mnt/EFI/BOOT/mmia32.efi
|
||||
rm -f ./tmp_mnt/ENROLL_THIS_KEY_IN_MOKMANAGER.cer
|
||||
mv ./tmp_mnt/EFI/BOOT/grubx64_real.efi ./tmp_mnt/EFI/BOOT/BOOTX64.EFI
|
||||
mv ./tmp_mnt/EFI/BOOT/grubia32_real.efi ./tmp_mnt/EFI/BOOT/BOOTIA32.EFI
|
||||
|
||||
sync
|
||||
|
||||
for tt in 1 2 3; do
|
||||
if umount ./tmp_mnt > /dev/null 2>&1; then
|
||||
vtdebug "umount part2 success"
|
||||
rm -rf ./tmp_mnt
|
||||
break
|
||||
else
|
||||
vtdebug "umount part2 failed, now retry..."
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
sleep 2
|
||||
check_umount_disk "$DISK"
|
||||
vtoycli partresize -s $DISK $part2_start
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
INSTALL/tool/i386/vtoycli
Normal file
BIN
INSTALL/tool/i386/vtoycli
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
INSTALL/tool/mips64el/vtoycli
Normal file
BIN
INSTALL/tool/mips64el/vtoycli
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -68,10 +68,10 @@ check_tool_work_ok() {
|
||||
return
|
||||
fi
|
||||
|
||||
if vtoyfat -T; then
|
||||
vtdebug "vtoyfat test ok ..."
|
||||
if vtoycli fat -T; then
|
||||
vtdebug "vtoycli fat test ok ..."
|
||||
else
|
||||
vtdebug "vtoyfat test fail ..."
|
||||
vtdebug "vtoycli fat test fail ..."
|
||||
ventoy_false
|
||||
return
|
||||
fi
|
||||
@@ -183,7 +183,7 @@ check_disk_secure_boot() {
|
||||
|
||||
PART2=$(get_disk_part_name $1 2)
|
||||
|
||||
vtoyfat -s $PART2
|
||||
vtoycli fat -s $PART2
|
||||
}
|
||||
|
||||
get_disk_ventoy_version() {
|
||||
@@ -195,7 +195,7 @@ get_disk_ventoy_version() {
|
||||
|
||||
PART2=$(get_disk_part_name $1 2)
|
||||
|
||||
ParseVer=$(vtoyfat $PART2)
|
||||
ParseVer=$(vtoycli fat $PART2)
|
||||
if [ $? -eq 0 ]; then
|
||||
vtdebug "Ventoy version in $PART2 is $ParseVer"
|
||||
echo $ParseVer
|
||||
@@ -391,7 +391,7 @@ format_ventoy_disk_gpt() {
|
||||
|
||||
sync
|
||||
|
||||
vtoygpt -f $DISK
|
||||
vtoycli gpt -f $DISK
|
||||
sync
|
||||
|
||||
udevadm trigger --name-match=$DISK >/dev/null 2>&1
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
INSTALL/tool/x86_64/vtoycli
Normal file
BIN
INSTALL/tool/x86_64/vtoycli
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -89,9 +89,9 @@ mkdir -p $tmpmnt/tool
|
||||
# cp $OPT ./tool/x86_64/mount.exfat-fuse $tmpmnt/tool/mount.exfat-fuse_x86_64
|
||||
# cp $OPT ./tool/aarch64/mount.exfat-fuse $tmpmnt/tool/mount.exfat-fuse_aarch64
|
||||
# to save space
|
||||
cp $OPT ./tool/i386/vtoygpt $tmpmnt/tool/mount.exfat-fuse_i386
|
||||
cp $OPT ./tool/x86_64/vtoygpt $tmpmnt/tool/mount.exfat-fuse_x86_64
|
||||
cp $OPT ./tool/aarch64/vtoygpt $tmpmnt/tool/mount.exfat-fuse_aarch64
|
||||
dd status=none bs=1024 count=16 if=./tool/i386/vtoycli of=$tmpmnt/tool/mount.exfat-fuse_i386
|
||||
dd status=none bs=1024 count=16 if=./tool/x86_64/vtoycli of=$tmpmnt/tool/mount.exfat-fuse_x86_64
|
||||
dd status=none bs=1024 count=16 if=./tool/aarch64/vtoycli of=$tmpmnt/tool/mount.exfat-fuse_aarch64
|
||||
|
||||
|
||||
rm -f $tmpmnt/grub/i386-pc/*.img
|
||||
|
@@ -77,9 +77,9 @@
|
||||
"STR_INSTALL_TIP":"디스크가 포맷되고 모든 데이터가 손실됩니다.#@계속하시겠습니까?",
|
||||
"STR_INSTALL_TIP2":"디스크가 포맷되고 모든 데이터가 손실됩니다.#@계속하시겠습니까? (다시 확인)",
|
||||
"STR_INSTALL_SUCCESS":"축하합니다!#@Ventoy가 장치에 성공적으로 설치되었습니다.",
|
||||
"STR_INSTALL_FAILED":"설치 중 오류가 발생했습니다. USB를 다시 연결하고 다시 시도할 수 있습니다. 자세한 내용은 log.txt를 확인하십시오.",
|
||||
"STR_INSTALL_FAILED":"설치 중 오류가 발생했습니다. USB를 다시 삽입하고 다시 시도할 수 있습니다. 자세한 내용은 log.txt를 확인하십시오.",
|
||||
"STR_UPDATE_SUCCESS":"축하합니다!#@Ventoy가 장치에 성공적으로 업데이트되었습니다.",
|
||||
"STR_UPDATE_FAILED":"업데이트 중에 오류가 발생했습니다. USB를 다시 연결하고 다시 시도할 수 있습니다. 자세한 내용은 log.txt를 확인하십시오.",
|
||||
"STR_UPDATE_FAILED":"업데이트 중에 오류가 발생했습니다. USB를 다시 삽입하고 다시 시도할 수 있습니다. 자세한 내용은 log.txt를 확인하십시오.",
|
||||
"STR_WAIT_PROCESS":"현재 작업이 실행 중입니다. 기다려 주십시오...",
|
||||
"STR_MENU_OPTION":"옵션",
|
||||
"STR_MENU_SECURE_BOOT":"보안 부트 (Secure Boot) 지원",
|
||||
@@ -90,7 +90,7 @@
|
||||
"STR_SPACE_VAL_INVALID":"예약된 공간의 값이 잘못되었습니다",
|
||||
"STR_MENU_CLEAR":"Ventoy 제거",
|
||||
"STR_CLEAR_SUCCESS":"Ventoy가 장치에서 성공적으로 제거되었습니다.",
|
||||
"STR_CLEAR_FAILED":"디스크에서 Ventoy를 지울 때 오류가 발생했습니다. USB를 다시 연결하고 다시 시도할 수 있습니다. 자세한 내용은 log.txt를 확인하십시오.",
|
||||
"STR_CLEAR_FAILED":"디스크에서 Ventoy를 지울 때 오류가 발생했습니다. USB를 다시 삽입하고 다시 시도할 수 있습니다. 자세한 내용은 log.txt를 확인하십시오.",
|
||||
"STR_MENU_PART_STYLE":"파티션 유형",
|
||||
"STR_DISK_2TB_MBR_ERROR":"2TB 이상의 디스크는 GPT를 선택하십시오",
|
||||
"STR_SHOW_ALL_DEV":"모든 장치 표시",
|
||||
@@ -103,14 +103,14 @@
|
||||
"STR_WEB_SERVICE_BUSY":"서비스가 사용 중입니다. 나중에 다시 시도하십시오.",
|
||||
"STR_MENU_VTSI_CREATE":"VTSI 파일 생성",
|
||||
"STR_VTSI_CREATE_TIP":"이번에는 장치에 쓰지 않고 VTSI 파일#@만 생성합니다.#@계속하시겠습니까?",
|
||||
"STR_VTSI_CREATE_SUCCESS":"VTSI 파일이 성공적으로 생성되었습니다!#@Rufus(3.15+)를 사용하여 장치에 기록하여 Ventoy 설치를 완료할 수 있습니다.",
|
||||
"STR_VTSI_CREATE_SUCCESS":"VTSI 파일이 성공적으로 생성되었습니다!#@Rufus (3.15+)를 사용하여 장치에 기록하여 Ventoy 설치를 완료할 수 있습니다.",
|
||||
"STR_VTSI_CREATE_FAILED":"VTSI 파일을 생성하지 못했습니다.",
|
||||
"STR_MENU_PART_RESIZE":"Non-destructive Install",
|
||||
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
|
||||
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
|
||||
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
|
||||
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
|
||||
|
||||
"STR_MENU_PART_RESIZE":"비파괴 설치",
|
||||
"STR_PART_RESIZE_TIP":"가능하면 Ventoy가 비파괴 설치를 시도합니다. #@계속하시겠습니까?",
|
||||
"STR_PART_RESIZE_SUCCESS":"축하합니다!#@Ventoy 비파괴 설치가 완료되었습니다.",
|
||||
"STR_PART_RESIZE_FAILED":"비파괴 설치에 실패했습니다. 자세한 내용은 log.txt를 확인하십시오.",
|
||||
"STR_PART_RESIZE_UNSUPPORTED":"일부 조건을 충족할 수 없기 때문에 Ventoy 비파괴 설치가 중지되었습니다. 자세한 내용은 log.txt를 확인하십시오.",
|
||||
|
||||
"STRXXX":""
|
||||
},
|
||||
{
|
||||
@@ -329,15 +329,15 @@
|
||||
"STR_WEB_SERVICE_UNAVAILABLE":"Błąd komunikacji: usługa niedostępna",
|
||||
"STR_WEB_TOKEN_MISMATCH":"Stan daemona został zaktualizowany, spróbuj ponownie później.",
|
||||
"STR_WEB_SERVICE_BUSY":"Usługa jest zajęta, spróbuj ponownie później.",
|
||||
"STR_MENU_VTSI_CREATE":"Generate VTSI File",
|
||||
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
|
||||
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
|
||||
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
|
||||
"STR_MENU_PART_RESIZE":"Non-destructive Install",
|
||||
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
|
||||
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
|
||||
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
|
||||
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
|
||||
"STR_MENU_VTSI_CREATE":"Wygeneruj plik VTSI",
|
||||
"STR_VTSI_CREATE_TIP":"Tym razem nie napisze do urządzenia ale tylko wygeneruje plik VTSI#@Kontynuować?",
|
||||
"STR_VTSI_CREATE_SUCCESS":"Pomyślnie wygenerowane plik VTSI!#@Możesz teraz użyć Rufus'a(3.15+) aby napisać go na urządzenie by dokończyć instlację Ventoy.",
|
||||
"STR_VTSI_CREATE_FAILED":"Generacja pliku VTSI nie powiodła się.",
|
||||
"STR_MENU_PART_RESIZE":"Nieniszcząsa instalacja",
|
||||
"STR_PART_RESIZE_TIP":"Ventoy spróbuje nieniszczącej instalacji jeśli jest możliwa. #@Kontynuować?",
|
||||
"STR_PART_RESIZE_SUCCESS":"Gratulacje!#@Nieniszcząca instlacja Ventoy zakończyła się pomyślnie.",
|
||||
"STR_PART_RESIZE_FAILED":"Nieniszcząca instalacja nie powiodła się, sprawdz log.txt po szczegóły.",
|
||||
"STR_PART_RESIZE_UNSUPPORTED":"Nieniszcząca instalacja Ventoy została zatrzymana ponieważ niektóre wymagania nie zostały spełnione. Sprawdz log.txt po szczegóły.",
|
||||
|
||||
"STRXXX":""
|
||||
},
|
||||
@@ -447,11 +447,11 @@
|
||||
"STR_VTSI_CREATE_TIP":"Şu an aygıta yazılmayacak,sadece bir VTSI dosyası oluşturulacak#@Devam edilsin mi?",
|
||||
"STR_VTSI_CREATE_SUCCESS":"VTSI dosyası başarılı bir şekilde oluşturuldu!#@Ventoy'un aygıta kurulumunu tamamlamak için Rufus(3.15+) programını kullanabilirsiniz.",
|
||||
"STR_VTSI_CREATE_FAILED":"VTSI dosyası oluşturma başarısız oldu!",
|
||||
"STR_MENU_PART_RESIZE":"Non-destructive Install",
|
||||
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
|
||||
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
|
||||
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
|
||||
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
|
||||
"STR_MENU_PART_RESIZE":"Tahribatsız Kurulum",
|
||||
"STR_PART_RESIZE_TIP":"Ventoy,mümkünse tahribatsız kurulumu deneyecektir. . #@Devam edilsin mi?",
|
||||
"STR_PART_RESIZE_SUCCESS":"Tebrikler!#@Ventoy Tahribatsız Kurulum, başarıyla tamamlandı.",
|
||||
"STR_PART_RESIZE_FAILED":"Tahribatsız kurulum başarısız oldu, ayrıntılar için log.txt dosyasını kontrol edin.",
|
||||
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy Tahribatsız Kurulum, bazı koşullar sağlanmadığı için durduruldu. Ayrıntılı bilgi için log.txt dosyasını kontrol edin.",
|
||||
|
||||
"STRXXX":""
|
||||
},
|
||||
@@ -500,15 +500,15 @@
|
||||
"STR_WEB_SERVICE_UNAVAILABLE":"Kommunikationsfehler: Dienst nicht verfügbar",
|
||||
"STR_WEB_TOKEN_MISMATCH":"Daemon-Status aktualisiert, bitte später erneut versuchen.",
|
||||
"STR_WEB_SERVICE_BUSY":"Dienst ist ausgelastet, bitte später erneut versuchen.",
|
||||
"STR_MENU_VTSI_CREATE":"Generate VTSI File",
|
||||
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
|
||||
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
|
||||
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
|
||||
"STR_MENU_VTSI_CREATE":"VTSI-Datei erstellen",
|
||||
"STR_VTSI_CREATE_TIP":"Es wird nur eine VTSI-Datei erstellt und nichts auf ein Gerät geschrieben.#@Fortfahren?",
|
||||
"STR_VTSI_CREATE_SUCCESS":"VTSI-Datei erfolgreich erstellt!#@Sie können Rufus(3.15+) zum auf das Gerät schreiben verwenden um die Installation von Ventoy fertigzustellen.",
|
||||
"STR_VTSI_CREATE_FAILED":"VTSI-Datei konnte nicht erstellt werden.",
|
||||
"STR_MENU_PART_RESIZE":"Non-destructive Install",
|
||||
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
|
||||
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
|
||||
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
|
||||
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
|
||||
"STR_PART_RESIZE_TIP":"Ventoy wird eine Installation ohne vorherige Formatierung versuchen. #@Fortfahren?",
|
||||
"STR_PART_RESIZE_SUCCESS":"Glückwunsch!#@Die Installation von Ventoy, ohne vorherige Formatierung, wurde erfolgreich abgeschlossen.",
|
||||
"STR_PART_RESIZE_FAILED":"Installation ohne vorherige Formatierung fehlgeschlagen. Für Details die log.txt prüfen.",
|
||||
"STR_PART_RESIZE_UNSUPPORTED":"Installation ohne vorherige Formatierung wurde auf Grund einiger nicht erfüllbarer Bedingungen gestoppt. Für Details die log.txt prüfen.",
|
||||
|
||||
"STRXXX":""
|
||||
},
|
||||
@@ -1086,56 +1086,56 @@
|
||||
"name":"Italian (Italiano)",
|
||||
"FontFamily":"Courier New",
|
||||
"FontSize":16,
|
||||
"Author":"AverageUser2,Albano Battistella",
|
||||
"Author":"AverageUser2,Albano Battistella,bovirus",
|
||||
|
||||
"STR_ERROR":"Errore",
|
||||
"STR_WARNING":"Attenzione",
|
||||
"STR_INFO":"Info",
|
||||
"STR_INCORRECT_DIR":"Si prega di eseguire nella cartella corretta",
|
||||
"STR_INCORRECT_TREE_DIR":"Non eseguire qui, scarica il pacchetto di installazione ed avvialo",
|
||||
"STR_INCORRECT_DIR":"Eseguilo nella cartella corretta",
|
||||
"STR_INCORRECT_TREE_DIR":"Non eseguirlo qui.#@Scarica il pacchetto di installazione ed avvialo.",
|
||||
"STR_DEVICE":"Dispositivo",
|
||||
"STR_LOCAL_VER":"Versione locale di Ventoy",
|
||||
"STR_DISK_VER":"Ventoy nel dispositivo",
|
||||
"STR_STATUS":"Stato - PRONTO",
|
||||
"STR_INSTALL":"Installa",
|
||||
"STR_UPDATE":"Aggiorna",
|
||||
"STR_UPDATE_TIP":"L'aggiornamento è sicuro, i file presenti nel dispositivo rimarranno invariati.#@Continuare?",
|
||||
"STR_INSTALL_TIP":"Il disco verrà formattato e tutti i dati saranno persi.#@Continuare?",
|
||||
"STR_INSTALL_TIP2":"Il disco verrà formattato e tutti i dati saranno persi.#@Continuare?' (seconda verifica)",
|
||||
"STR_INSTALL_SUCCESS":"Congratulazioni!#@Ventoy è stato installato con successo nel dispositivo",
|
||||
"STR_INSTALL_FAILED":"Si è verificato un errore durante l'installazione. Riconnetti il dispostivo e riprova. Controlla il file log.txt per i dettagli.",
|
||||
"STR_UPDATE_SUCCESS":"Congratulazioni!#@Ventoy è stato aggiornato con successo nel dispositivo",
|
||||
"STR_UPDATE_FAILED":"Si è verificato un errore durante l'aggiornamento. Riconnetti il dispostivo e riprova. Controlla il file log.txt per i dettagli.",
|
||||
"STR_WAIT_PROCESS":"Un processo è in esecuzione, attendere prego...",
|
||||
"STR_UPDATE_TIP":"L'aggiornamento è sicuro, i file presenti nel dispositivo rimarranno invariati.#@Vuoi continuare?",
|
||||
"STR_INSTALL_TIP":"Il disco verrà formattato e tutti i dati saranno persi.#@Vuoi continuare?",
|
||||
"STR_INSTALL_TIP2":"Il disco verrà formattato e tutti i dati saranno persi.#@Vuoi continuare (seconda verifica)?",
|
||||
"STR_INSTALL_SUCCESS":"Congratulazioni!#@Installazione di Ventoy nel dispositivo completata.",
|
||||
"STR_INSTALL_FAILED":"Si è verificato un errore durante l'installazione.#@Riconnetti il dispositivo e riprova.#@Per i dettagli controlla il file log.txt .",
|
||||
"STR_UPDATE_SUCCESS":"Congratulazioni!#@Aggiornamento di Ventoy nel dispositivo completato",
|
||||
"STR_UPDATE_FAILED":"Si è verificato un errore durante l'aggiornamento.#@Riconnetti il dispositivo e riprova.#@Per i dettagli controlla il file log.txt.",
|
||||
"STR_WAIT_PROCESS":"Un processo è in esecuzione. Attendi...",
|
||||
"STR_MENU_OPTION":"Opzioni",
|
||||
"STR_MENU_SECURE_BOOT":"Avvio protetto (secure boot)",
|
||||
"STR_MENU_PART_CFG":"Configurazione della partizione",
|
||||
"STR_MENU_PART_CFG":"Configurazione partizione",
|
||||
"STR_BTN_OK":"OK",
|
||||
"STR_BTN_CANCEL":"Annulla",
|
||||
"STR_PRESERVE_SPACE":"Riserva spazio nella parte finale del disco",
|
||||
"STR_SPACE_VAL_INVALID":"Quantità di spazio da riservare non valida",
|
||||
"STR_MENU_CLEAR":"Rimuovi Ventoy",
|
||||
"STR_CLEAR_SUCCESS":"Ventoy è stato rimosso con successo dal dispositivo.",
|
||||
"STR_CLEAR_FAILED":"Si è verificato un errore durante la rimozione di Ventoy dal dispositivo. Riconnetti il dispositivo e riprova. Controlla il file log.txt per maggiori dettagli",
|
||||
"STR_MENU_PART_STYLE":"Stile Tabella delle partizioni",
|
||||
"STR_CLEAR_SUCCESS":"Rimozione di Ventoy dal dispositivo completata.",
|
||||
"STR_CLEAR_FAILED":"Si è verificato un errore durante la rimozione di Ventoy dal dispositivo.#@Riconnetti il dispositivo e riprova.#@Per i dettagli controlla il file log.txt.",
|
||||
"STR_MENU_PART_STYLE":"Stile tabella partizioni",
|
||||
"STR_DISK_2TB_MBR_ERROR":"Seleziona GPT per dischi con dimensioni maggiori di 2TB",
|
||||
"STR_SHOW_ALL_DEV":"Mostra tutti i dispositivi",
|
||||
"STR_SHOW_ALL_DEV":"Visualizza tutti i dispositivi",
|
||||
"STR_PART_ALIGN_4KB":"Allinea le partizioni con 4KB",
|
||||
"STR_WEB_COMMUNICATION_ERR":"Errore di comunicazione:",
|
||||
"STR_WEB_REMOTE_ABNORMAL":"Errore di comunicazione: remoto anormale",
|
||||
"STR_WEB_REQUEST_TIMEOUT":"Errore di comunicazione: richiesta scaduta",
|
||||
"STR_WEB_SERVICE_UNAVAILABLE":"Errore di comunicazione: servizio non disponibile",
|
||||
"STR_WEB_TOKEN_MISMATCH":"Stato del demone aggiornato, riprova più tardi.",
|
||||
"STR_WEB_SERVICE_BUSY":"Il servizio è occupato, riprova più tardi.",
|
||||
"STR_WEB_TOKEN_MISMATCH":"Stato del demone aggiornato. Riprova più tardi.",
|
||||
"STR_WEB_SERVICE_BUSY":"Il servizio è occupato. Riprova più tardi.",
|
||||
"STR_MENU_VTSI_CREATE":"Genera file VTSI",
|
||||
"STR_VTSI_CREATE_TIP":"Questa volta non scriverà sul dispositivo, ma genererà solo un file VTSI#@Continuare?",
|
||||
"STR_VTSI_CREATE_SUCCESS":"File VTSI creato con successo!#@Puoi usare Rufus (versione 3.15 o successiva) per scrivere sul dispositivo in modo da completare l'installazione di Ventoy.",
|
||||
"STR_VTSI_CREATE_FAILED":"Creazione File VTSI non riuscito.",
|
||||
"STR_MENU_PART_RESIZE":"Non-destructive Install",
|
||||
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
|
||||
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
|
||||
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
|
||||
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
|
||||
"STR_VTSI_CREATE_TIP":"Questa volta non scriverà sul dispositivo, ma genererà solo un file VTSI#@Vuoi continuare?",
|
||||
"STR_VTSI_CREATE_SUCCESS":"Creazione file VTSI completata!#@Per scrivere nel dispositivo in modo da completare l'installazione di Ventoy puoi usare Rufus (versione 3.15 o successiva).",
|
||||
"STR_VTSI_CREATE_FAILED":"Creazione file VTSI non riuscita.",
|
||||
"STR_MENU_PART_RESIZE":"Installazione non distruttiva",
|
||||
"STR_PART_RESIZE_TIP":"Ventoy proverà, se possibile, l'installazione non distruttiva.#@Vuoi continuare?",
|
||||
"STR_PART_RESIZE_SUCCESS":"Congratulazioni!#@Installazione non distruttiva di Ventoy completata.",
|
||||
"STR_PART_RESIZE_FAILED":"Installazione non distruttiva non riuscita.#@Per i dettagli controlla il file log.txt.",
|
||||
"STR_PART_RESIZE_UNSUPPORTED":"L'installazione non distruttiva di Ventoy è stata interrotta perché alcune condizioni non possono essere soddisfatte.#@Per i dettagli controlla il file log.txt.",
|
||||
|
||||
"STRXXX":""
|
||||
},
|
||||
@@ -2336,4 +2336,4 @@
|
||||
|
||||
"STRXXX":""
|
||||
}
|
||||
]
|
||||
]
|
||||
|
@@ -117,11 +117,9 @@ See [https://www.ventoy.net/en/faq.html](https://www.ventoy.net/en/faq.html) for
|
||||
It would be much appreciated if you want to make a small donation to support my work!
|
||||
Alipay, WeChat Pay, PayPal and Bitcoin are avaliable for donation. You can chose any of them.
|
||||
|
||||
**Alipay**
|
||||
[https://www.ventoy.net/static/img/AliPay.png](https://www.ventoy.net/static/img/AliPay.png)
|
||||
|
||||
**WeChat Pay**
|
||||
[https://www.ventoy.net/static/img/WeChatPay.png](https://www.ventoy.net/static/img/WeChatPay.png)
|
||||
Alipay | WeChat Pay
|
||||
-|-
|
||||
<img src="https://www.ventoy.net/static/img/AliPay.png" width="250" height="250">|<img src="https://www.ventoy.net/static/img/WeChatPay.png" width="250" height="250">
|
||||
|
||||
**PayPal**
|
||||
You can transfer to my paypal account `admin@ventoy.net` or just click [https://www.paypal.me/ventoy](https://www.paypal.me/ventoy)
|
||||
|
111
Ventoy2Disk/Ventoy2Disk/DiskService.c
Normal file
111
Ventoy2Disk/Ventoy2Disk/DiskService.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/******************************************************************************
|
||||
* DiskService.c
|
||||
*
|
||||
* 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 <Windows.h>
|
||||
#include <winternl.h>
|
||||
#include <commctrl.h>
|
||||
#include <initguid.h>
|
||||
#include <vds.h>
|
||||
#include "Ventoy2Disk.h"
|
||||
#include "DiskService.h"
|
||||
|
||||
BOOL DISK_CleanDisk(int DriveIndex)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
ret = VDS_CleanDisk(DriveIndex);
|
||||
if (!ret)
|
||||
{
|
||||
ret = PSHELL_CleanDisk(DriveIndex);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
BOOL DISK_DeleteVtoyEFIPartition(int DriveIndex, UINT64 EfiPartOffset)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
ret = VDS_DeleteVtoyEFIPartition(DriveIndex, EfiPartOffset);
|
||||
if (!ret)
|
||||
{
|
||||
ret = PSHELL_DeleteVtoyEFIPartition(DriveIndex, EfiPartOffset);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL DISK_ChangeVtoyEFI2ESP(int DriveIndex, UINT64 Offset)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
ret = VDS_ChangeVtoyEFI2ESP(DriveIndex, Offset);
|
||||
if (!ret)
|
||||
{
|
||||
ret = PSHELL_ChangeVtoyEFI2ESP(DriveIndex, Offset);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
BOOL DISK_ChangeVtoyEFI2Basic(int DriveIndex, UINT64 Offset)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
ret = VDS_ChangeVtoyEFI2Basic(DriveIndex, Offset);
|
||||
if (!ret)
|
||||
{
|
||||
ret = PSHELL_ChangeVtoyEFI2Basic(DriveIndex, Offset);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL DISK_ChangeVtoyEFIAttr(int DriveIndex, UINT64 Offset, UINT64 Attr)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
ret = VDS_ChangeVtoyEFIAttr(DriveIndex, Offset, Attr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL DISK_ShrinkVolume(int DriveIndex, const char* VolumeGuid, CHAR DriveLetter, UINT64 OldBytes, UINT64 ReduceBytes)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
ret = VDS_ShrinkVolume(DriveIndex, VolumeGuid, DriveLetter, OldBytes, ReduceBytes);
|
||||
if (!ret)
|
||||
{
|
||||
if (LASTERR == VDS_E_SHRINK_DIRTY_VOLUME)
|
||||
{
|
||||
Log("VDS shrink return dirty, no need to run powershell.");
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = PSHELL_ShrinkVolume(DriveIndex, VolumeGuid, DriveLetter, OldBytes, ReduceBytes);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -29,24 +29,39 @@ typedef struct VDS_PARA
|
||||
WCHAR Name[36];
|
||||
ULONG NameLen;
|
||||
ULONGLONG Offset;
|
||||
CHAR DriveLetter;
|
||||
}VDS_PARA;
|
||||
|
||||
//DISK API
|
||||
BOOL DISK_CleanDisk(int DriveIndex);
|
||||
BOOL DISK_DeleteVtoyEFIPartition(int DriveIndex, UINT64 EfiPartOffset);
|
||||
BOOL DISK_ChangeVtoyEFIAttr(int DriveIndex, UINT64 Offset, UINT64 Attr);
|
||||
BOOL DISK_ChangeVtoyEFI2ESP(int DriveIndex, UINT64 Offset);
|
||||
BOOL DISK_ChangeVtoyEFI2Basic(int DriveIndex, UINT64 Offset);
|
||||
BOOL DISK_ShrinkVolume(int DriveIndex, const char* VolumeGuid, CHAR DriveLetter, UINT64 OldBytes, UINT64 ReduceBytes);
|
||||
|
||||
|
||||
|
||||
//VDS com
|
||||
int VDS_Init(void);
|
||||
BOOL VDS_CleanDisk(int DriveIndex);
|
||||
BOOL VDS_DeleteAllPartitions(int DriveIndex);
|
||||
BOOL VDS_DeleteVtoyEFIPartition(int DriveIndex);
|
||||
BOOL VDS_ChangeVtoyEFIAttr(int DriveIndex, UINT64 Attr);
|
||||
BOOL VDS_CreateVtoyEFIPart(int DriveIndex, UINT64 Offset);
|
||||
BOOL VDS_DeleteVtoyEFIPartition(int DriveIndex, UINT64 EfiPartOffset);
|
||||
BOOL VDS_ChangeVtoyEFIAttr(int DriveIndex, UINT64 Offset, UINT64 Attr);
|
||||
BOOL VDS_ChangeVtoyEFI2ESP(int DriveIndex, UINT64 Offset);
|
||||
BOOL VDS_ChangeVtoyEFI2Basic(int DriveIndex, UINT64 Offset);
|
||||
BOOL VDS_FormatVtoyEFIPart(int DriveIndex, UINT64 Offset);
|
||||
BOOL VDS_ShrinkVolume(const char* VolumeGuid, UINT64 ReduceBytes);
|
||||
BOOL VDS_ShrinkVolume(int DriveIndex, const char* VolumeGuid, CHAR DriveLetter, UINT64 OldBytes, UINT64 ReduceBytes);
|
||||
BOOL VDS_IsLastAvaliable(void);
|
||||
|
||||
|
||||
//diskpart.exe
|
||||
BOOL DSPT_CleanDisk(int DriveIndex);
|
||||
|
||||
//powershell.exe
|
||||
BOOL PSHELL_CleanDisk(int DriveIndex);
|
||||
BOOL PSHELL_DeleteVtoyEFIPartition(int DriveIndex, UINT64 EfiPartOffset);
|
||||
BOOL PSHELL_ChangeVtoyEFI2ESP(int DriveIndex, UINT64 Offset);
|
||||
BOOL PSHELL_ChangeVtoyEFI2Basic(int DriveIndex, UINT64 Offset);
|
||||
BOOL PSHELL_ShrinkVolume(int DriveIndex, const char* VolumeGuid, CHAR DriveLetter, UINT64 OldBytes, UINT64 ReduceBytes);
|
||||
|
||||
//
|
||||
// Internel define
|
||||
|
@@ -64,6 +64,9 @@ STATIC BOOL DSPT_CommProc(const char *Cmd)
|
||||
WaitForSingleObject(Pi.hProcess, INFINITE);
|
||||
Log("Process finished...");
|
||||
|
||||
CHECK_CLOSE_HANDLE(Pi.hProcess);
|
||||
CHECK_CLOSE_HANDLE(Pi.hThread);
|
||||
|
||||
DeleteFileA(CmdFile);
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -390,6 +390,10 @@ static const char *GetVdsError(DWORD error_code)
|
||||
return "The offline operation failed.";
|
||||
case 0x80042598: // VDS_E_BAD_REVISION_NUMBER
|
||||
return "The operation could not be completed because the specified revision number is not supported.";
|
||||
case 0x80042599: // VDS_E_SHRINK_USER_CANCELLED
|
||||
return "The shrink operation was cancelled by the user.";
|
||||
case 0x8004259a: // VDS_E_SHRINK_DIRTY_VOLUME
|
||||
return "The volume you have selected to shrink may be corrupted. Use Chkdsk to fix the corruption problem, and then try again.";
|
||||
case 0x00042700: // VDS_S_NAME_TRUNCATED
|
||||
return "The name was set successfully but had to be truncated.";
|
||||
case 0x80042701: // VDS_E_NAME_NOT_UNIQUE
|
||||
@@ -601,6 +605,13 @@ const char *WindowsErrorString(DWORD error_code)
|
||||
|
||||
typedef BOOL(*VDS_Callback_PF)(void *pInterface, VDS_DISK_PROP *pDiskProp, UINT64 data);
|
||||
|
||||
static BOOL g_vds_available = TRUE;
|
||||
|
||||
BOOL VDS_IsLastAvaliable(void)
|
||||
{
|
||||
return g_vds_available;
|
||||
}
|
||||
|
||||
STATIC IVdsService * VDS_InitService(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
@@ -627,6 +638,7 @@ STATIC IVdsService * VDS_InitService(void)
|
||||
{
|
||||
VDS_SET_ERROR(hr);
|
||||
Log("Could not load VDS Service: 0x%x", LASTERR);
|
||||
g_vds_available = FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -640,6 +652,7 @@ STATIC IVdsService * VDS_InitService(void)
|
||||
}
|
||||
|
||||
Log("VDS init OK, service %p", pService);
|
||||
g_vds_available = TRUE;
|
||||
return pService;
|
||||
}
|
||||
|
||||
@@ -1061,16 +1074,16 @@ STATIC BOOL VDS_CallBack_DeletePartition(void *pInterface, VDS_DISK_PROP *pDiskP
|
||||
HRESULT hr;
|
||||
VDS_PARTITION_PROP* prop_array = NULL;
|
||||
LONG i, prop_array_size;
|
||||
ULONG PartNumber = (ULONG)data;
|
||||
UINT64 PartOffset = data;
|
||||
IVdsAdvancedDisk *pAdvancedDisk = (IVdsAdvancedDisk *)pInterface;
|
||||
|
||||
if (PartNumber == 0)
|
||||
if (PartOffset == 0)
|
||||
{
|
||||
Log("Deleting ALL partitions from disk '%S':", pDiskProp->pwszName);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Deleting partition(%ld) from disk '%S':", PartNumber, pDiskProp->pwszName);
|
||||
Log("Deleting partition(offset=%llu) from disk '%S':", PartOffset, pDiskProp->pwszName);
|
||||
}
|
||||
|
||||
// Query the partition data, so we can get the start offset, which we need for deletion
|
||||
@@ -1080,7 +1093,7 @@ STATIC BOOL VDS_CallBack_DeletePartition(void *pInterface, VDS_DISK_PROP *pDiskP
|
||||
r = TRUE;
|
||||
for (i = 0; i < prop_array_size; i++)
|
||||
{
|
||||
if (PartNumber == 0 || PartNumber == prop_array[i].ulPartitionNumber)
|
||||
if (PartOffset == 0 || PartOffset == prop_array[i].ullOffset)
|
||||
{
|
||||
Log("* Partition %d (offset: %lld, size: %llu) delete it.",
|
||||
prop_array[i].ulPartitionNumber, prop_array[i].ullOffset, (ULONGLONG)prop_array[i].ullSize);
|
||||
@@ -1127,9 +1140,9 @@ BOOL VDS_DeleteAllPartitions(int DriveIndex)
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL VDS_DeleteVtoyEFIPartition(int DriveIndex)
|
||||
BOOL VDS_DeleteVtoyEFIPartition(int DriveIndex, UINT64 EfiPartOffset)
|
||||
{
|
||||
BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK, DriveIndex, VDS_CallBack_DeletePartition, 2);
|
||||
BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK, DriveIndex, VDS_CallBack_DeletePartition, EfiPartOffset);
|
||||
Log("VDS_DeleteVtoyEFIPartition %d ret:%d (%s)", DriveIndex, ret, ret ? "SUCCESS" : "FAIL");
|
||||
return ret;
|
||||
}
|
||||
@@ -1138,6 +1151,7 @@ STATIC BOOL VDS_CallBack_ChangeEFIAttr(void *pInterface, VDS_DISK_PROP *pDiskPro
|
||||
{
|
||||
BOOL r = FALSE;
|
||||
HRESULT hr;
|
||||
VDS_PARA *VdsPara = (VDS_PARA *)data;
|
||||
VDS_PARTITION_PROP* prop_array = NULL;
|
||||
LONG i, prop_array_size;
|
||||
CHANGE_ATTRIBUTES_PARAMETERS AttrPara;
|
||||
@@ -1151,12 +1165,13 @@ STATIC BOOL VDS_CallBack_ChangeEFIAttr(void *pInterface, VDS_DISK_PROP *pDiskPro
|
||||
{
|
||||
if (prop_array[i].ullSize == VENTOY_EFI_PART_SIZE &&
|
||||
prop_array[i].PartitionStyle == VDS_PST_GPT &&
|
||||
memcmp(prop_array[i].Gpt.name, L"VTOYEFI", 7 * 2) == 0)
|
||||
memcmp(prop_array[i].Gpt.name, L"VTOYEFI", 7 * 2) == 0 &&
|
||||
VdsPara->Offset == prop_array[i].ullOffset)
|
||||
{
|
||||
Log("* Partition %d (offset: %lld, size: %llu, Attr:0x%llx)", prop_array[i].ulPartitionNumber,
|
||||
Log("** Partition %d (offset: %lld, size: %llu, Attr:0x%llx)", prop_array[i].ulPartitionNumber,
|
||||
prop_array[i].ullOffset, (ULONGLONG)prop_array[i].ullSize, prop_array[i].Gpt.attributes);
|
||||
|
||||
if (prop_array[i].Gpt.attributes == data)
|
||||
if (prop_array[i].Gpt.attributes == VdsPara->Attr)
|
||||
{
|
||||
Log("Attribute match, No need to change.");
|
||||
r = TRUE;
|
||||
@@ -1164,7 +1179,7 @@ STATIC BOOL VDS_CallBack_ChangeEFIAttr(void *pInterface, VDS_DISK_PROP *pDiskPro
|
||||
else
|
||||
{
|
||||
AttrPara.style = VDS_PST_GPT;
|
||||
AttrPara.GptPartInfo.attributes = data;
|
||||
AttrPara.GptPartInfo.attributes = VdsPara->Attr;
|
||||
hr = IVdsAdvancedDisk_ChangeAttributes(pAdvancedDisk, prop_array[i].ullOffset, &AttrPara);
|
||||
if (hr == S_OK)
|
||||
{
|
||||
@@ -1191,10 +1206,15 @@ STATIC BOOL VDS_CallBack_ChangeEFIAttr(void *pInterface, VDS_DISK_PROP *pDiskPro
|
||||
return r;
|
||||
}
|
||||
|
||||
BOOL VDS_ChangeVtoyEFIAttr(int DriveIndex, UINT64 Attr)
|
||||
BOOL VDS_ChangeVtoyEFIAttr(int DriveIndex, UINT64 Offset, UINT64 Attr)
|
||||
{
|
||||
BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK, DriveIndex, VDS_CallBack_ChangeEFIAttr, Attr);
|
||||
Log("VDS_ChangeVtoyEFIAttr %d ret:%d (%s)", DriveIndex, ret, ret ? "SUCCESS" : "FAIL");
|
||||
VDS_PARA Para;
|
||||
|
||||
Para.Attr = Attr;
|
||||
Para.Offset = Offset;
|
||||
|
||||
BOOL ret = VDS_DiskCommProc(INTF_ADVANCEDDISK, DriveIndex, VDS_CallBack_ChangeEFIAttr, (UINT64)&Para);
|
||||
Log("VDS_ChangeVtoyEFIAttr %d (offset:%llu) ret:%d (%s)", DriveIndex, Offset, ret, ret ? "SUCCESS" : "FAIL");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1238,6 +1258,7 @@ BOOL VDS_ChangeVtoyEFI2ESP(int DriveIndex, UINT64 Offset)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
BOOL VDS_ChangeVtoyEFI2Basic(int DriveIndex, UINT64 Offset)
|
||||
{
|
||||
VDS_PARA Para;
|
||||
@@ -1251,153 +1272,69 @@ BOOL VDS_ChangeVtoyEFI2Basic(int DriveIndex, UINT64 Offset)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
STATIC BOOL VDS_CallBack_CreateVtoyEFI(void *pInterface, VDS_DISK_PROP *pDiskProp, UINT64 data)
|
||||
STATIC BOOL CHKDSK_Volume(CHAR LogicalDrive)
|
||||
{
|
||||
HRESULT hr, hr2;
|
||||
ULONG completed;
|
||||
IVdsAsync* pAsync;
|
||||
CREATE_PARTITION_PARAMETERS para;
|
||||
IVdsCreatePartitionEx *pCreatePartitionEx = (IVdsCreatePartitionEx *)pInterface;
|
||||
VDS_PARA *VdsPara = (VDS_PARA *)data;
|
||||
CHAR CmdBuf[1024];
|
||||
STARTUPINFOA Si;
|
||||
PROCESS_INFORMATION Pi;
|
||||
|
||||
(void)pDiskProp;
|
||||
|
||||
memset(¶, 0, sizeof(para));
|
||||
para.style = VDS_PST_GPT;
|
||||
memcpy(&(para.GptPartInfo.partitionType), &VdsPara->Type, sizeof(GUID));
|
||||
memcpy(&(para.GptPartInfo.partitionId), &VdsPara->Id, sizeof(GUID));
|
||||
para.GptPartInfo.attributes = VdsPara->Attr;
|
||||
memcpy(para.GptPartInfo.name, VdsPara->Name, sizeof(WCHAR)* VdsPara->NameLen);
|
||||
|
||||
hr = IVdsCreatePartitionEx_CreatePartitionEx(pCreatePartitionEx, VdsPara->Offset, VENTOY_EFI_PART_SIZE, 512, ¶, &pAsync);
|
||||
while (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IVdsAsync_QueryStatus(pAsync, &hr2, &completed);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = hr2;
|
||||
if (hr == S_OK)
|
||||
{
|
||||
Log("Disk create partition QueryStatus OK, %lu%%", completed);
|
||||
break;
|
||||
}
|
||||
else if (hr == VDS_E_OPERATION_PENDING)
|
||||
{
|
||||
Log("Disk partition finish: %lu%%", completed);
|
||||
hr = S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("QueryStatus invalid status:0x%lx", hr);
|
||||
}
|
||||
}
|
||||
Sleep(1000);
|
||||
}
|
||||
|
||||
if (hr != S_OK)
|
||||
{
|
||||
VDS_SET_ERROR(hr);
|
||||
Log("Could not create partition, err:0x%lx(%s)", LASTERR, WindowsErrorString(hr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL VDS_CreateVtoyEFIPart(int DriveIndex, UINT64 Offset)
|
||||
{
|
||||
VDS_PARA Para;
|
||||
GUID WindowsDataPartType = { 0xebd0a0a2, 0xb9e5, 0x4433, { 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 } };
|
||||
GUID EspPartType = { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } };
|
||||
|
||||
Log("VDS_CreateVtoyEFIPart %u Offset:%llu Sector:%llu", DriveIndex, Offset, Offset / 512);
|
||||
|
||||
memset(&Para, 0, sizeof(Para));
|
||||
Para.Attr = 0x8000000000000000ULL;
|
||||
Para.Offset = Offset;
|
||||
memcpy(Para.Name, L"VTOYEFI", 7 * 2);
|
||||
Para.NameLen = 7;
|
||||
memcpy(&(Para.Type), &EspPartType, sizeof(GUID));
|
||||
CoCreateGuid(&(Para.Id));
|
||||
|
||||
BOOL ret = VDS_DiskCommProc(INTF_CREATEPARTITIONEX, DriveIndex, VDS_CallBack_CreateVtoyEFI, (UINT64)&Para);
|
||||
Log("VDS_CreateVtoyEFIPart %d ret:%d (%s)", DriveIndex, ret, ret ? "SUCCESS" : "FAIL");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
STATIC BOOL VDS_CallBack_FormatVtoyEFI(void *pInterface, VDS_DISK_PROP *pDiskProp, UINT64 data)
|
||||
{
|
||||
HRESULT hr, hr2;
|
||||
ULONG completed;
|
||||
IVdsAsync* pAsync;
|
||||
IVdsDiskPartitionMF *pPartitionMF = (IVdsDiskPartitionMF *)pInterface;
|
||||
VDS_PARA *VdsPara = (VDS_PARA *)data;
|
||||
|
||||
(void)pDiskProp;
|
||||
|
||||
hr = IVdsPartitionMF_FormatPartitionEx(pPartitionMF, VdsPara->Offset, L"FAT", 0x0100, 0, VdsPara->Name, TRUE, TRUE, FALSE, &pAsync);
|
||||
while (SUCCEEDED(hr))
|
||||
if ((!IsFileExist("C:\\Windows\\System32\\chkdsk.exe")) || (LogicalDrive == 0))
|
||||
{
|
||||
hr = IVdsAsync_QueryStatus(pAsync, &hr2, &completed);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = hr2;
|
||||
if (hr == S_OK)
|
||||
{
|
||||
Log("Disk format partition QueryStatus OK, %lu%%", completed);
|
||||
break;
|
||||
}
|
||||
else if (hr == VDS_E_OPERATION_PENDING)
|
||||
{
|
||||
Log("Disk format finish: %lu%%", completed);
|
||||
hr = S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("QueryStatus invalid status:0x%lx", hr);
|
||||
}
|
||||
}
|
||||
Sleep(1000);
|
||||
}
|
||||
|
||||
if (hr != S_OK)
|
||||
{
|
||||
VDS_SET_ERROR(hr);
|
||||
Log("Could not format partition, err:0x%lx (%s)", LASTERR, WindowsErrorString(hr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GetStartupInfoA(&Si);
|
||||
Si.dwFlags |= STARTF_USESHOWWINDOW;
|
||||
Si.wShowWindow = SW_HIDE;
|
||||
|
||||
sprintf_s(CmdBuf, sizeof(CmdBuf), "C:\\Windows\\System32\\chkdsk.exe %C: /f", LogicalDrive);
|
||||
|
||||
Log("CreateProcess <%s>", CmdBuf);
|
||||
CreateProcessA(NULL, CmdBuf, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
|
||||
|
||||
Log("Wair process ...");
|
||||
WaitForSingleObject(Pi.hProcess, INFINITE);
|
||||
Log("Process finished...");
|
||||
|
||||
CHECK_CLOSE_HANDLE(Pi.hProcess);
|
||||
CHECK_CLOSE_HANDLE(Pi.hThread);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Not supported for removable disk
|
||||
BOOL VDS_FormatVtoyEFIPart(int DriveIndex, UINT64 Offset)
|
||||
{
|
||||
VDS_PARA Para;
|
||||
|
||||
memset(&Para, 0, sizeof(Para));
|
||||
Para.Offset = Offset;
|
||||
memcpy(Para.Name, L"VTOYEFI", 7 * 2);
|
||||
|
||||
BOOL ret = VDS_DiskCommProc(INTF_PARTITIONMF, DriveIndex, VDS_CallBack_FormatVtoyEFI, (UINT64)&Para);
|
||||
Log("VDS_FormatVtoyEFIPart %d ret:%d (%s)", DriveIndex, ret, ret ? "SUCCESS" : "FAIL");
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC BOOL VDS_CallBack_ShrinkVolume(void* pInterface, VDS_DISK_PROP* pDiskProp, UINT64 data)
|
||||
{
|
||||
int i;
|
||||
HRESULT hr, hr2;
|
||||
IVdsVolume* pVolume = (IVdsVolume*)pInterface;
|
||||
ULONG completed;
|
||||
IVdsAsync* pAsync;
|
||||
VDS_PARA *VdsPara = (VDS_PARA *)data;
|
||||
|
||||
(void)pDiskProp;
|
||||
|
||||
Log("VDS_CallBack_ShrinkVolume (%llu) ...", (ULONGLONG)data);
|
||||
Log("VDS_CallBack_ShrinkVolume (%C:) (%llu) ...", VdsPara->DriveLetter, (ULONGLONG)VdsPara->Offset);
|
||||
|
||||
hr = IVdsVolume_Shrink(pVolume, (ULONGLONG)data, &pAsync);
|
||||
hr = IVdsVolume_Shrink(pVolume, (ULONGLONG)VdsPara->Offset, &pAsync);
|
||||
if (hr == VDS_E_SHRINK_DIRTY_VOLUME)
|
||||
{
|
||||
Log("Volume %C: is dirty, run chkdsk and retry.", VdsPara->DriveLetter);
|
||||
CHKDSK_Volume(VdsPara->DriveLetter);
|
||||
|
||||
hr = IVdsVolume_Shrink(pVolume, (ULONGLONG)VdsPara->Offset, &pAsync);
|
||||
if (hr == VDS_E_SHRINK_DIRTY_VOLUME)
|
||||
{
|
||||
Log("################################################################");
|
||||
Log("################################################################");
|
||||
for (i = 0; i < 20; i++)
|
||||
{
|
||||
Log("###### Volume dirty, Please run \"chkdsk /f %C:\" and retry. ######", VdsPara->Name[0]);
|
||||
}
|
||||
Log("################################################################");
|
||||
Log("################################################################");
|
||||
}
|
||||
}
|
||||
|
||||
while (SUCCEEDED(hr))
|
||||
{
|
||||
@@ -1427,18 +1364,24 @@ STATIC BOOL VDS_CallBack_ShrinkVolume(void* pInterface, VDS_DISK_PROP* pDiskProp
|
||||
{
|
||||
VDS_SET_ERROR(hr);
|
||||
Log("Could not ShrinkVolume, 0x%x err:0x%lx (%s)", hr, LASTERR, WindowsErrorString(hr));
|
||||
|
||||
VDS_SET_ERROR(hr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL VDS_ShrinkVolume(const char* VolumeGuid, UINT64 ReduceBytes)
|
||||
BOOL VDS_ShrinkVolume(int DriveIndex, const char* VolumeGuid, CHAR DriveLetter, UINT64 OldBytes, UINT64 ReduceBytes)
|
||||
{
|
||||
int i;
|
||||
BOOL ret = FALSE;
|
||||
WCHAR wGuid[128] = { 0 };
|
||||
const char *guid = NULL;
|
||||
VDS_PARA Para;
|
||||
|
||||
(VOID)DriveIndex;
|
||||
(VOID)OldBytes;
|
||||
|
||||
guid = strstr(VolumeGuid, "{");
|
||||
if (!guid)
|
||||
@@ -1451,7 +1394,10 @@ BOOL VDS_ShrinkVolume(const char* VolumeGuid, UINT64 ReduceBytes)
|
||||
wGuid[i] = guid[i];
|
||||
}
|
||||
|
||||
ret = VDS_VolumeCommProc(INTF_VOLUME, wGuid, VDS_CallBack_ShrinkVolume, ReduceBytes);
|
||||
Log("VDS_ShrinkVolume ret:%d (%s)", ret, ret ? "SUCCESS" : "FAIL");
|
||||
Para.Offset = ReduceBytes;
|
||||
Para.DriveLetter = DriveLetter;
|
||||
|
||||
ret = VDS_VolumeCommProc(INTF_VOLUME, wGuid, VDS_CallBack_ShrinkVolume, (UINT64)&Para);
|
||||
Log("VDS_ShrinkVolume %C: ret:%d (%s)", DriveLetter, ret, ret ? "SUCCESS" : "FAIL");
|
||||
return ret;
|
||||
}
|
@@ -23,5 +23,235 @@
|
||||
#include <commctrl.h>
|
||||
#include <initguid.h>
|
||||
#include <vds.h>
|
||||
#include <VersionHelpers.h>
|
||||
#include "Ventoy2Disk.h"
|
||||
#include "DiskService.h"
|
||||
|
||||
STATIC BOOL IsPowershellExist(void)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
if (!IsWindows8OrGreater())
|
||||
{
|
||||
Log("This is before Windows8 powershell disk not supported.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ret = IsFileExist("C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe");
|
||||
if (!ret)
|
||||
{
|
||||
Log("powershell.exe not exist");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int PSHELL_GetPartitionNumber(int PhyDrive, UINT64 Offset)
|
||||
{
|
||||
int partnum = -1;
|
||||
DWORD i = 0;
|
||||
DWORD BufLen = 0;
|
||||
DWORD dwBytes = 0;
|
||||
BOOL bRet;
|
||||
HANDLE hDrive;
|
||||
LONGLONG PartStart;
|
||||
DRIVE_LAYOUT_INFORMATION_EX *pDriveLayout = NULL;
|
||||
|
||||
Log("PSHELL_GetPartitionNumber PhyDrive:%d Offset:%llu", PhyDrive, Offset);
|
||||
|
||||
hDrive = GetPhysicalHandle(PhyDrive, FALSE, FALSE, FALSE);
|
||||
if (hDrive == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
BufLen = (DWORD)(sizeof(PARTITION_INFORMATION_EX)* 256);
|
||||
|
||||
pDriveLayout = malloc(BufLen);
|
||||
if (!pDriveLayout)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
memset(pDriveLayout, 0, BufLen);
|
||||
|
||||
bRet = DeviceIoControl(hDrive,
|
||||
IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL,
|
||||
0,
|
||||
pDriveLayout,
|
||||
BufLen,
|
||||
&dwBytes,
|
||||
NULL);
|
||||
if (!bRet)
|
||||
{
|
||||
Log("Failed to ioctrl get drive layout ex %u", LASTERR);
|
||||
goto out;
|
||||
}
|
||||
|
||||
Log("PhyDrive:%d PartitionStyle=%s PartitionCount=%u", PhyDrive,
|
||||
(pDriveLayout->PartitionStyle == PARTITION_STYLE_MBR) ? "MBR" : "GPT", pDriveLayout->PartitionCount);
|
||||
|
||||
for (i = 0; i < pDriveLayout->PartitionCount; i++)
|
||||
{
|
||||
PartStart = pDriveLayout->PartitionEntry[i].StartingOffset.QuadPart;
|
||||
if (PartStart == (LONGLONG)Offset)
|
||||
{
|
||||
Log("[*] [%d] PartitionNumber=%u Offset=%lld Length=%lld ",
|
||||
i,
|
||||
pDriveLayout->PartitionEntry[i].PartitionNumber,
|
||||
pDriveLayout->PartitionEntry[i].StartingOffset.QuadPart,
|
||||
pDriveLayout->PartitionEntry[i].PartitionLength.QuadPart
|
||||
);
|
||||
partnum = (int)pDriveLayout->PartitionEntry[i].PartitionNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("[ ] [%d] PartitionNumber=%u Offset=%lld Length=%lld ",
|
||||
i,
|
||||
pDriveLayout->PartitionEntry[i].PartitionNumber,
|
||||
pDriveLayout->PartitionEntry[i].StartingOffset.QuadPart,
|
||||
pDriveLayout->PartitionEntry[i].PartitionLength.QuadPart
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
CHECK_CLOSE_HANDLE(hDrive);
|
||||
CHECK_FREE(pDriveLayout);
|
||||
|
||||
return partnum;
|
||||
}
|
||||
|
||||
|
||||
STATIC BOOL PSHELL_CommProc(const char *Cmd)
|
||||
{
|
||||
CHAR CmdBuf[4096];
|
||||
STARTUPINFOA Si;
|
||||
PROCESS_INFORMATION Pi;
|
||||
|
||||
if (!IsPowershellExist())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GetStartupInfoA(&Si);
|
||||
Si.dwFlags |= STARTF_USESHOWWINDOW;
|
||||
Si.wShowWindow = SW_HIDE;
|
||||
|
||||
sprintf_s(CmdBuf, sizeof(CmdBuf), "C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe -Command \"&{ %s }\"", Cmd);
|
||||
|
||||
Log("CreateProcess <%s>", CmdBuf);
|
||||
CreateProcessA(NULL, CmdBuf, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
|
||||
|
||||
Log("Wair process ...");
|
||||
WaitForSingleObject(Pi.hProcess, INFINITE);
|
||||
Log("Process finished...");
|
||||
|
||||
CHECK_CLOSE_HANDLE(Pi.hProcess);
|
||||
CHECK_CLOSE_HANDLE(Pi.hThread);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
BOOL PSHELL_CleanDisk(int DriveIndex)
|
||||
{
|
||||
BOOL ret;
|
||||
CHAR CmdBuf[512];
|
||||
|
||||
sprintf_s(CmdBuf, sizeof(CmdBuf), "Clear-Disk -Number %d -RemoveData -RemoveOEM -Confirm:$false", DriveIndex);
|
||||
ret = PSHELL_CommProc(CmdBuf);
|
||||
Log("CleanDiskByPowershell<%d> ret:%d (%s)", DriveIndex, ret, ret ? "SUCCESS" : "FAIL");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
BOOL PSHELL_DeleteVtoyEFIPartition(int DriveIndex, UINT64 EfiPartOffset)
|
||||
{
|
||||
int Part;
|
||||
BOOL ret;
|
||||
CHAR CmdBuf[512];
|
||||
|
||||
Part = PSHELL_GetPartitionNumber(DriveIndex, EfiPartOffset);
|
||||
if (Part < 0)
|
||||
{
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf_s(CmdBuf, sizeof(CmdBuf), "Remove-Partition -DiskNumber %d -PartitionNumber %d -Confirm:$false", DriveIndex, Part);
|
||||
ret = PSHELL_CommProc(CmdBuf);
|
||||
}
|
||||
|
||||
Log("PSHELL_DeleteVtoyEFIPartition<%d> ret:%d (%s)", DriveIndex, ret, ret ? "SUCCESS" : "FAIL");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
BOOL PSHELL_ChangeVtoyEFI2ESP(int DriveIndex, UINT64 Offset)
|
||||
{
|
||||
int Part;
|
||||
BOOL ret;
|
||||
CHAR CmdBuf[512];
|
||||
|
||||
Part = PSHELL_GetPartitionNumber(DriveIndex, Offset);
|
||||
if (Part < 0)
|
||||
{
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf_s(CmdBuf, sizeof(CmdBuf), "Set-Partition -DiskNumber %d -PartitionNumber %d -gpttype '{C12A7328-F81F-11D2-BA4B-00A0C93EC93B}' -Confirm:$false", DriveIndex, Part);
|
||||
ret = PSHELL_CommProc(CmdBuf);
|
||||
}
|
||||
|
||||
Log("PSHELL_ChangeVtoyEFI2ESP<%d> ret:%d (%s)", DriveIndex, ret, ret ? "SUCCESS" : "FAIL");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
BOOL PSHELL_ChangeVtoyEFI2Basic(int DriveIndex, UINT64 Offset)
|
||||
{
|
||||
int Part;
|
||||
BOOL ret;
|
||||
CHAR CmdBuf[512];
|
||||
|
||||
Part = PSHELL_GetPartitionNumber(DriveIndex, Offset);
|
||||
if (Part < 0)
|
||||
{
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf_s(CmdBuf, sizeof(CmdBuf), "Set-Partition -DiskNumber %d -PartitionNumber %d -gpttype '{ebd0a0a2-b9e5-4433-87c0-68b6b72699c7}' -Confirm:$false", DriveIndex, Part);
|
||||
ret = PSHELL_CommProc(CmdBuf);
|
||||
}
|
||||
|
||||
Log("PSHELL_ChangeVtoyEFI2Basic<%d> ret:%d (%s)", DriveIndex, ret, ret ? "SUCCESS" : "FAIL");
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL PSHELL_ShrinkVolume(int DriveIndex, const char* VolumeGuid, CHAR DriveLetter, UINT64 OldBytes, UINT64 ReduceBytes)
|
||||
{
|
||||
int Part;
|
||||
BOOL ret;
|
||||
CHAR CmdBuf[512];
|
||||
|
||||
(void)VolumeGuid;
|
||||
|
||||
Part = PSHELL_GetPartitionNumber(DriveIndex, SIZE_1MB);
|
||||
if (Part < 0)
|
||||
{
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf_s(CmdBuf, sizeof(CmdBuf), "Resize-Partition -DiskNumber %d -PartitionNumber %d -Size %llu -Confirm:$false",
|
||||
DriveIndex, Part, OldBytes - ReduceBytes);
|
||||
ret = PSHELL_CommProc(CmdBuf);
|
||||
}
|
||||
|
||||
Log("PSHELL_ShrinkVolume<%d> %C: ret:%d (%s)", DriveIndex, DriveLetter, ret, ret ? "SUCCESS" : "FAIL");
|
||||
return ret;
|
||||
}
|
||||
|
@@ -1127,9 +1127,17 @@ static int FormatPart1exFAT(UINT64 DiskSizeBytes)
|
||||
|
||||
Log("Formatting Part1 exFAT ...");
|
||||
|
||||
disk_io_reset_write_error();
|
||||
|
||||
Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024);
|
||||
if (FR_OK == Ret)
|
||||
{
|
||||
if (disk_io_is_write_error())
|
||||
{
|
||||
Log("Formatting Part1 exFAT failed, write error.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Log("Formatting Part1 exFAT success");
|
||||
return 0;
|
||||
}
|
||||
@@ -1851,7 +1859,18 @@ End:
|
||||
}
|
||||
else
|
||||
{
|
||||
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
|
||||
|
||||
FindProcessOccupyDisk(hDrive, pPhyDrive);
|
||||
|
||||
if (!VDS_IsLastAvaliable())
|
||||
{
|
||||
Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
|
||||
Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
|
||||
Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
|
||||
Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
|
||||
Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
|
||||
}
|
||||
}
|
||||
|
||||
if (pGptInfo)
|
||||
@@ -1917,7 +1936,7 @@ int PartitionResizeForVentoy(PHY_DRIVE_INFO *pPhyDrive)
|
||||
if (pPhyDrive->ResizeNoShrink == FALSE)
|
||||
{
|
||||
Log("Need to shrink the volume");
|
||||
if (VDS_ShrinkVolume(pPhyDrive->ResizeVolumeGuid, RecudeBytes))
|
||||
if (DISK_ShrinkVolume(pPhyDrive->PhyDrive, pPhyDrive->ResizeVolumeGuid, pPhyDrive->Part1DriveLetter, pPhyDrive->ResizeOldPart1Size, RecudeBytes))
|
||||
{
|
||||
Log("Shrink volume success, now check again");
|
||||
|
||||
@@ -2011,6 +2030,7 @@ int PartitionResizeForVentoy(PHY_DRIVE_INFO *pPhyDrive)
|
||||
memcpy(pMBR->PartTbl + (j + 1), pMBR->PartTbl + j, sizeof(PART_TABLE));
|
||||
}
|
||||
|
||||
memset(pMBR->PartTbl + 1, 0, sizeof(PART_TABLE));
|
||||
VentoyFillMBRLocation(pPhyDrive->SizeInBytes, (UINT32)pPhyDrive->ResizePart2StartSector, VENTOY_EFI_PART_SIZE / 512, pMBR->PartTbl + 1);
|
||||
pMBR->PartTbl[0].Active = 0x80; // bootable
|
||||
pMBR->PartTbl[1].Active = 0x00;
|
||||
@@ -2048,6 +2068,7 @@ int PartitionResizeForVentoy(PHY_DRIVE_INFO *pPhyDrive)
|
||||
pMBR->BootCode[92] = 0x22;
|
||||
|
||||
// to fix windows issue
|
||||
memset(pGPT->PartTbl + 1, 0, sizeof(VTOY_GPT_PART_TBL));
|
||||
memcpy(&(pGPT->PartTbl[1].PartType), &WindowsDataPartType, sizeof(GUID));
|
||||
CoCreateGuid(&(pGPT->PartTbl[1].PartGuid));
|
||||
|
||||
@@ -2058,6 +2079,7 @@ int PartitionResizeForVentoy(PHY_DRIVE_INFO *pPhyDrive)
|
||||
|
||||
//Update CRC
|
||||
pGPT->Head.PartTblCrc = VentoyCrc32(pGPT->PartTbl, sizeof(pGPT->PartTbl));
|
||||
pGPT->Head.Crc = 0;
|
||||
pGPT->Head.Crc = VentoyCrc32(&(pGPT->Head), pGPT->Head.Length);
|
||||
|
||||
Log("pGPT->Head.EfiStartLBA=%llu", (ULONGLONG)pGPT->Head.EfiStartLBA);
|
||||
@@ -2320,6 +2342,7 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
|
||||
BOOL Esp2Basic = FALSE;
|
||||
BOOL ChangeAttr = FALSE;
|
||||
BOOL CleanDisk = FALSE;
|
||||
BOOL DelEFI = FALSE;
|
||||
BOOL bWriteBack = TRUE;
|
||||
HANDLE hVolume;
|
||||
HANDLE hDrive;
|
||||
@@ -2335,6 +2358,7 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
|
||||
MBR_HEAD MBR;
|
||||
BYTE *pBackup = NULL;
|
||||
VTOY_GPT_INFO *pGptInfo = NULL;
|
||||
VTOY_GPT_INFO *pGptBkup = NULL;
|
||||
UINT8 ReservedData[4096];
|
||||
|
||||
Log("#####################################################");
|
||||
@@ -2356,17 +2380,19 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
|
||||
|
||||
if (pPhyDrive->PartStyle)
|
||||
{
|
||||
pGptInfo = malloc(sizeof(VTOY_GPT_INFO));
|
||||
pGptInfo = malloc(2 * sizeof(VTOY_GPT_INFO));
|
||||
if (!pGptInfo)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));
|
||||
memset(pGptInfo, 0, 2 * sizeof(VTOY_GPT_INFO));
|
||||
pGptBkup = pGptInfo + 1;
|
||||
|
||||
// Read GPT Info
|
||||
SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
|
||||
ReadFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL);
|
||||
memcpy(pGptBkup, pGptInfo, sizeof(VTOY_GPT_INFO));
|
||||
|
||||
//MBR will be used to compare with local boot image
|
||||
memcpy(&MBR, &pGptInfo->MBR, sizeof(MBR_HEAD));
|
||||
@@ -2430,7 +2456,7 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
|
||||
if (TryId == 1)
|
||||
{
|
||||
Log("Change GPT partition type to ESP");
|
||||
if (VDS_ChangeVtoyEFI2ESP(pPhyDrive->PhyDrive, StartSector * 512))
|
||||
if (DISK_ChangeVtoyEFI2ESP(pPhyDrive->PhyDrive, StartSector * 512ULL))
|
||||
{
|
||||
Esp2Basic = TRUE;
|
||||
Sleep(3000);
|
||||
@@ -2439,13 +2465,18 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
|
||||
else if (TryId == 2)
|
||||
{
|
||||
Log("Change GPT partition attribute");
|
||||
if (VDS_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, 0x8000000000000001))
|
||||
if (DISK_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, StartSector * 512ULL, 0x8000000000000001))
|
||||
{
|
||||
ChangeAttr = TRUE;
|
||||
Sleep(2000);
|
||||
}
|
||||
}
|
||||
else if (TryId == 3)
|
||||
{
|
||||
DISK_DeleteVtoyEFIPartition(pPhyDrive->PhyDrive, StartSector * 512ULL);
|
||||
DelEFI = TRUE;
|
||||
}
|
||||
else if (TryId == 4)
|
||||
{
|
||||
Log("Clean disk GPT partition table");
|
||||
if (BackupDataBeforeCleanDisk(pPhyDrive->PhyDrive, pPhyDrive->SizeInBytes, &pBackup))
|
||||
@@ -2457,11 +2488,7 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
|
||||
|
||||
Log("Success to backup data before clean");
|
||||
CleanDisk = TRUE;
|
||||
if (!VDS_CleanDisk(pPhyDrive->PhyDrive))
|
||||
{
|
||||
Sleep(3000);
|
||||
DSPT_CleanDisk(pPhyDrive->PhyDrive);
|
||||
}
|
||||
DISK_CleanDisk(pPhyDrive->PhyDrive);
|
||||
Sleep(3000);
|
||||
}
|
||||
else
|
||||
@@ -2504,6 +2531,10 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
|
||||
|
||||
Status = ERROR_NOT_FOUND;
|
||||
}
|
||||
else if (DelEFI)
|
||||
{
|
||||
Status = ERROR_NOT_FOUND;
|
||||
}
|
||||
else if (Esp2Basic)
|
||||
{
|
||||
Status = ERROR_NOT_FOUND;
|
||||
@@ -2595,7 +2626,7 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
|
||||
CHECK_CLOSE_HANDLE(hDrive);
|
||||
|
||||
Log("Now delete partition 2...");
|
||||
VDS_DeleteVtoyEFIPartition(pPhyDrive->PhyDrive);
|
||||
DISK_DeleteVtoyEFIPartition(pPhyDrive->PhyDrive, StartSector * 512ULL);
|
||||
|
||||
hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
|
||||
if (hDrive == INVALID_HANDLE_VALUE)
|
||||
@@ -2707,6 +2738,37 @@ int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int TryId)
|
||||
|
||||
Sleep(1000);
|
||||
}
|
||||
else if (DelEFI)
|
||||
{
|
||||
VTOY_GPT_HDR BackupHdr;
|
||||
|
||||
VentoyFillBackupGptHead(pGptBkup, &BackupHdr);
|
||||
if (!WriteBackupDataToDisk(hDrive, 512 * pGptBkup->Head.EfiBackupLBA, (BYTE*)(&BackupHdr), 512))
|
||||
{
|
||||
bWriteBack = FALSE;
|
||||
}
|
||||
|
||||
if (!WriteBackupDataToDisk(hDrive, 512 * (pGptBkup->Head.EfiBackupLBA - 32), (BYTE*)(pGptBkup->PartTbl), 32 * 512))
|
||||
{
|
||||
bWriteBack = FALSE;
|
||||
}
|
||||
|
||||
if (!WriteBackupDataToDisk(hDrive, 512, (BYTE*)pGptBkup + 512, 33 * 512))
|
||||
{
|
||||
bWriteBack = FALSE;
|
||||
}
|
||||
|
||||
if (bWriteBack)
|
||||
{
|
||||
Log("Write backup partition table success");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Write backup partition table failed");
|
||||
}
|
||||
|
||||
Sleep(1000);
|
||||
}
|
||||
|
||||
//Refresh Drive Layout
|
||||
DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
|
||||
@@ -2726,6 +2788,7 @@ End:
|
||||
}
|
||||
else
|
||||
{
|
||||
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
|
||||
FindProcessOccupyDisk(hDrive, pPhyDrive);
|
||||
}
|
||||
|
||||
@@ -2734,7 +2797,7 @@ End:
|
||||
if (Esp2Basic)
|
||||
{
|
||||
Log("Recover GPT partition type to basic");
|
||||
VDS_ChangeVtoyEFI2Basic(pPhyDrive->PhyDrive, StartSector * 512);
|
||||
DISK_ChangeVtoyEFI2Basic(pPhyDrive->PhyDrive, StartSector * 512);
|
||||
}
|
||||
|
||||
if (pPhyDrive->PartStyle == 1)
|
||||
@@ -2742,7 +2805,7 @@ End:
|
||||
if (ChangeAttr || ((pPhyDrive->Part2GPTAttr >> 56) != 0xC0))
|
||||
{
|
||||
Log("Change EFI partition attr %u <0x%llx> to <0x%llx>", ChangeAttr, pPhyDrive->Part2GPTAttr, 0xC000000000000001ULL);
|
||||
if (VDS_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, 0xC000000000000001ULL))
|
||||
if (DISK_ChangeVtoyEFIAttr(pPhyDrive->PhyDrive, StartSector * 512ULL, 0xC000000000000001ULL))
|
||||
{
|
||||
Log("Change EFI partition attr success");
|
||||
pPhyDrive->Part2GPTAttr = 0xC000000000000001ULL;
|
||||
|
@@ -73,6 +73,17 @@ void Log(const char *Fmt, ...)
|
||||
|
||||
}
|
||||
|
||||
const char* GUID2String(void *guid, char *buf, int len)
|
||||
{
|
||||
GUID* pGUID = (GUID*)guid;
|
||||
sprintf_s(buf, len, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
||||
pGUID->Data1, pGUID->Data2, pGUID->Data3,
|
||||
pGUID->Data4[0], pGUID->Data4[1],
|
||||
pGUID->Data4[2], pGUID->Data4[3], pGUID->Data4[4], pGUID->Data4[5], pGUID->Data4[6], pGUID->Data4[7]
|
||||
);
|
||||
return buf;
|
||||
}
|
||||
|
||||
BOOL IsPathExist(BOOL Dir, const char *Fmt, ...)
|
||||
{
|
||||
va_list Arg;
|
||||
@@ -231,6 +242,7 @@ BOOL IsWow64(void)
|
||||
typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
|
||||
LPFN_ISWOW64PROCESS fnIsWow64Process;
|
||||
BOOL bIsWow64 = FALSE;
|
||||
CHAR Wow64Dir[MAX_PATH];
|
||||
|
||||
fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process");
|
||||
if (NULL != fnIsWow64Process)
|
||||
@@ -238,6 +250,15 @@ BOOL IsWow64(void)
|
||||
fnIsWow64Process(GetCurrentProcess(), &bIsWow64);
|
||||
}
|
||||
|
||||
if (!bIsWow64)
|
||||
{
|
||||
if (GetSystemWow64DirectoryA(Wow64Dir, sizeof(Wow64Dir)))
|
||||
{
|
||||
Log("GetSystemWow64DirectoryA=<%s>", Wow64Dir);
|
||||
bIsWow64 = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return bIsWow64;
|
||||
}
|
||||
|
||||
|
@@ -81,6 +81,8 @@ static BOOL IsVentoyPhyDrive(int PhyDrive, UINT64 SizeBytes, MBR_HEAD *pMBR, UIN
|
||||
UINT32 PartStartSector;
|
||||
UINT32 PartSectorCount;
|
||||
CHAR PhyDrivePath[128];
|
||||
CHAR GUIDStr[128];
|
||||
GUID ZeroGuid = { 0 };
|
||||
VTOY_GPT_INFO *pGpt = NULL;
|
||||
|
||||
safe_sprintf(PhyDrivePath, "\\\\.\\PhysicalDrive%d", PhyDrive);
|
||||
@@ -108,20 +110,7 @@ static BOOL IsVentoyPhyDrive(int PhyDrive, UINT64 SizeBytes, MBR_HEAD *pMBR, UIN
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
Log("=========== Disk%d Partition Table %d ============", PhyDrive, i + 1);
|
||||
Log("PartTbl.Active = 0x%x", MBR.PartTbl[i].Active);
|
||||
Log("PartTbl.FsFlag = 0x%x", MBR.PartTbl[i].FsFlag);
|
||||
Log("PartTbl.StartSectorId = %u", MBR.PartTbl[i].StartSectorId);
|
||||
Log("PartTbl.SectorCount = %u", MBR.PartTbl[i].SectorCount);
|
||||
Log("PartTbl.StartHead = %u", MBR.PartTbl[i].StartHead);
|
||||
Log("PartTbl.StartSector = %u", MBR.PartTbl[i].StartSector);
|
||||
Log("PartTbl.StartCylinder = %u", MBR.PartTbl[i].StartCylinder);
|
||||
Log("PartTbl.EndHead = %u", MBR.PartTbl[i].EndHead);
|
||||
Log("PartTbl.EndSector = %u", MBR.PartTbl[i].EndSector);
|
||||
Log("PartTbl.EndCylinder = %u", MBR.PartTbl[i].EndCylinder);
|
||||
}
|
||||
|
||||
|
||||
if (MBR.PartTbl[0].FsFlag == 0xEE)
|
||||
{
|
||||
@@ -147,6 +136,23 @@ static BOOL IsVentoyPhyDrive(int PhyDrive, UINT64 SizeBytes, MBR_HEAD *pMBR, UIN
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
{
|
||||
if (memcmp(&(pGpt->PartTbl[i].PartGuid), &ZeroGuid, sizeof(GUID)) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Log("=========== Disk%d GPT Partition %d ============", PhyDrive, i + 1);
|
||||
|
||||
Log("PartTbl.PartType = %s", GUID2String(&pGpt->PartTbl[i].PartType, GUIDStr, sizeof(GUIDStr)));
|
||||
Log("PartTbl.PartGuid = %s", GUID2String(&pGpt->PartTbl[i].PartGuid, GUIDStr, sizeof(GUIDStr)));
|
||||
Log("PartTbl.StartLBA = %llu", (ULONGLONG)pGpt->PartTbl[i].StartLBA);
|
||||
Log("PartTbl.LastLBA = %llu", (ULONGLONG)pGpt->PartTbl[i].LastLBA);
|
||||
Log("PartTbl.Attribute = 0x%llx", pGpt->PartTbl[i].Attr);
|
||||
Log("PartTbl.Name = %S", pGpt->PartTbl[i].Name);
|
||||
}
|
||||
|
||||
if (memcmp(pGpt->PartTbl[1].Name, L"VTOYEFI", 7 * 2))
|
||||
{
|
||||
if (pGpt->PartTbl[1].Name[0])
|
||||
@@ -187,6 +193,21 @@ static BOOL IsVentoyPhyDrive(int PhyDrive, UINT64 SizeBytes, MBR_HEAD *pMBR, UIN
|
||||
{
|
||||
CHECK_CLOSE_HANDLE(hDrive);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
Log("=========== Disk%d MBR Partition %d ============", PhyDrive, i + 1);
|
||||
Log("PartTbl.Active = 0x%x", MBR.PartTbl[i].Active);
|
||||
Log("PartTbl.FsFlag = 0x%x", MBR.PartTbl[i].FsFlag);
|
||||
Log("PartTbl.StartSectorId = %u", MBR.PartTbl[i].StartSectorId);
|
||||
Log("PartTbl.SectorCount = %u", MBR.PartTbl[i].SectorCount);
|
||||
Log("PartTbl.StartHead = %u", MBR.PartTbl[i].StartHead);
|
||||
Log("PartTbl.StartSector = %u", MBR.PartTbl[i].StartSector);
|
||||
Log("PartTbl.StartCylinder = %u", MBR.PartTbl[i].StartCylinder);
|
||||
Log("PartTbl.EndHead = %u", MBR.PartTbl[i].EndHead);
|
||||
Log("PartTbl.EndSector = %u", MBR.PartTbl[i].EndSector);
|
||||
Log("PartTbl.EndCylinder = %u", MBR.PartTbl[i].EndCylinder);
|
||||
}
|
||||
|
||||
if (MBR.PartTbl[0].StartSectorId != 2048)
|
||||
{
|
||||
Log("Part1 not match %u", MBR.PartTbl[0].StartSectorId);
|
||||
|
@@ -167,6 +167,8 @@ typedef struct PHY_DRIVE_INFO
|
||||
UINT64 Part2GPTAttr;
|
||||
|
||||
BOOL ResizeNoShrink;
|
||||
UINT64 ResizeOldPart1Size;
|
||||
CHAR Part1DriveLetter;
|
||||
CHAR ResizeVolumeGuid[64];
|
||||
CHAR FsName[64];
|
||||
UINT64 ResizePart2StartSector;
|
||||
@@ -319,6 +321,9 @@ void disk_io_reset_imghook(int *psegnum, UINT64 *pDataOffset);
|
||||
|
||||
HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare);
|
||||
void InitComboxCtrl(HWND hWnd, int PhyDrive);
|
||||
int disk_io_is_write_error(void);
|
||||
void disk_io_reset_write_error(void);
|
||||
const char* GUID2String(void* guid, char* buf, int len);
|
||||
|
||||
#define VTSI_SUPPORT 1
|
||||
|
||||
|
@@ -335,6 +335,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="crc32.c" />
|
||||
<ClCompile Include="DiskService.c" />
|
||||
<ClCompile Include="DiskService_diskpart.c" />
|
||||
<ClCompile Include="DiskService_vds.c" />
|
||||
<ClCompile Include="DiskService_wmsa.c" />
|
||||
|
@@ -90,6 +90,9 @@
|
||||
<ClCompile Include="DiskService_wmsa.c">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DiskService.c">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Ventoy2Disk.h">
|
||||
|
Binary file not shown.
@@ -30,6 +30,20 @@ VTSI_SEGMENT *g_VentoySegment = NULL;
|
||||
int g_VentoyMaxSeg = 0;
|
||||
int g_VentoyCurSeg = -1;
|
||||
UINT64 g_VentoyDataOffset = 0;
|
||||
int g_write_error = 0;
|
||||
int g_error_print_cnt = 0;
|
||||
|
||||
void disk_io_reset_write_error(void)
|
||||
{
|
||||
g_write_error = 0;
|
||||
g_error_print_cnt = 0;
|
||||
}
|
||||
|
||||
|
||||
int disk_io_is_write_error(void)
|
||||
{
|
||||
return g_write_error;
|
||||
}
|
||||
|
||||
void disk_io_set_param(HANDLE Handle, UINT64 SectorCount)
|
||||
{
|
||||
@@ -248,9 +262,15 @@ DRESULT disk_write (
|
||||
|
||||
bRet = WriteFile(g_hPhyDrive, buff, count * 512, &dwSize, NULL);
|
||||
|
||||
if (dwSize != count * 512)
|
||||
if ((!bRet) || (dwSize != count * 512))
|
||||
{
|
||||
Log("WriteFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u", bRet, count * 512, dwSize, GetLastError());
|
||||
g_write_error = 1;
|
||||
g_error_print_cnt++;
|
||||
|
||||
if (g_error_print_cnt <= 10)
|
||||
{
|
||||
Log("WriteFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u", bRet, count * 512, dwSize, GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
return RES_OK;
|
||||
|
37
vtoycli/build.sh
Normal file
37
vtoycli/build.sh
Normal file
@@ -0,0 +1,37 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -f vtoycli_64
|
||||
rm -f vtoycli_32
|
||||
rm -f vtoycli_aa64
|
||||
rm -f vtoycli_m64e
|
||||
|
||||
SRCS="vtoycli.c vtoyfat.c vtoygpt.c crc32.c partresize.c"
|
||||
|
||||
gcc -specs "/usr/local/musl/lib/musl-gcc.specs" -Os -static -D_FILE_OFFSET_BITS=64 $SRCS -Ifat_io_lib/include fat_io_lib/lib/libfat_io_64.a -o vtoycli_64
|
||||
|
||||
/opt/diet32/bin/diet -Os gcc -D_FILE_OFFSET_BITS=64 -m32 $SRCS -Ifat_io_lib/include fat_io_lib/lib/libfat_io_32.a -o vtoycli_32
|
||||
|
||||
|
||||
#gcc -O2 -D_FILE_OFFSET_BITS=64 $SRCS -Ifat_io_lib/include fat_io_lib/lib/libfat_io_64.a -o vtoycli_64
|
||||
#gcc -m32 -O2 -D_FILE_OFFSET_BITS=64 $SRCS -Ifat_io_lib/include fat_io_lib/lib/libfat_io_32.a -o vtoycli_32
|
||||
|
||||
aarch64-buildroot-linux-uclibc-gcc -static -O2 -D_FILE_OFFSET_BITS=64 $SRCS -Ifat_io_lib/include fat_io_lib/lib/libfat_io_aa64.a -o vtoycli_aa64
|
||||
mips64el-linux-musl-gcc -mips64r2 -mabi=64 -static -O2 -D_FILE_OFFSET_BITS=64 $SRCS -Ifat_io_lib/include fat_io_lib/lib/libfat_io_m64e.a -o vtoycli_m64e
|
||||
|
||||
|
||||
if [ -e vtoycli_64 ] && [ -e vtoycli_32 ] && [ -e vtoycli_aa64 ] && [ -e vtoycli_m64e ]; then
|
||||
echo -e "\n===== success $name =======\n"
|
||||
|
||||
strip --strip-all vtoycli_32
|
||||
strip --strip-all vtoycli_64
|
||||
aarch64-buildroot-linux-uclibc-strip --strip-all vtoycli_aa64
|
||||
mips64el-linux-musl-strip --strip-all vtoycli_m64e
|
||||
|
||||
[ -d ../INSTALL/tool/i386/ ] && mv vtoycli_32 ../INSTALL/tool/i386/vtoycli
|
||||
[ -d ../INSTALL/tool/x86_64/ ] && mv vtoycli_64 ../INSTALL/tool/x86_64/vtoycli
|
||||
[ -d ../INSTALL/tool/aarch64/ ] && mv vtoycli_aa64 ../INSTALL/tool/aarch64/vtoycli
|
||||
[ -d ../INSTALL/tool/mips64el/ ] && mv vtoycli_m64e ../INSTALL/tool/mips64el/vtoycli
|
||||
else
|
||||
echo -e "\n===== failed =======\n"
|
||||
exit 1
|
||||
fi
|
305
vtoycli/crc32.c
Normal file
305
vtoycli/crc32.c
Normal file
@@ -0,0 +1,305 @@
|
||||
/******************************************************************************
|
||||
* vtoygpt.c ---- ventoy gpt util
|
||||
*
|
||||
* Copyright (c) 2020, 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define VOID void
|
||||
#define CHAR char
|
||||
#define UINT64 unsigned long long
|
||||
#define UINT32 unsigned int
|
||||
#define UINT16 unsigned short
|
||||
#define CHAR16 unsigned short
|
||||
#define UINT8 unsigned char
|
||||
|
||||
UINT32 g_crc_table[256] = {
|
||||
0x00000000,
|
||||
0x77073096,
|
||||
0xEE0E612C,
|
||||
0x990951BA,
|
||||
0x076DC419,
|
||||
0x706AF48F,
|
||||
0xE963A535,
|
||||
0x9E6495A3,
|
||||
0x0EDB8832,
|
||||
0x79DCB8A4,
|
||||
0xE0D5E91E,
|
||||
0x97D2D988,
|
||||
0x09B64C2B,
|
||||
0x7EB17CBD,
|
||||
0xE7B82D07,
|
||||
0x90BF1D91,
|
||||
0x1DB71064,
|
||||
0x6AB020F2,
|
||||
0xF3B97148,
|
||||
0x84BE41DE,
|
||||
0x1ADAD47D,
|
||||
0x6DDDE4EB,
|
||||
0xF4D4B551,
|
||||
0x83D385C7,
|
||||
0x136C9856,
|
||||
0x646BA8C0,
|
||||
0xFD62F97A,
|
||||
0x8A65C9EC,
|
||||
0x14015C4F,
|
||||
0x63066CD9,
|
||||
0xFA0F3D63,
|
||||
0x8D080DF5,
|
||||
0x3B6E20C8,
|
||||
0x4C69105E,
|
||||
0xD56041E4,
|
||||
0xA2677172,
|
||||
0x3C03E4D1,
|
||||
0x4B04D447,
|
||||
0xD20D85FD,
|
||||
0xA50AB56B,
|
||||
0x35B5A8FA,
|
||||
0x42B2986C,
|
||||
0xDBBBC9D6,
|
||||
0xACBCF940,
|
||||
0x32D86CE3,
|
||||
0x45DF5C75,
|
||||
0xDCD60DCF,
|
||||
0xABD13D59,
|
||||
0x26D930AC,
|
||||
0x51DE003A,
|
||||
0xC8D75180,
|
||||
0xBFD06116,
|
||||
0x21B4F4B5,
|
||||
0x56B3C423,
|
||||
0xCFBA9599,
|
||||
0xB8BDA50F,
|
||||
0x2802B89E,
|
||||
0x5F058808,
|
||||
0xC60CD9B2,
|
||||
0xB10BE924,
|
||||
0x2F6F7C87,
|
||||
0x58684C11,
|
||||
0xC1611DAB,
|
||||
0xB6662D3D,
|
||||
0x76DC4190,
|
||||
0x01DB7106,
|
||||
0x98D220BC,
|
||||
0xEFD5102A,
|
||||
0x71B18589,
|
||||
0x06B6B51F,
|
||||
0x9FBFE4A5,
|
||||
0xE8B8D433,
|
||||
0x7807C9A2,
|
||||
0x0F00F934,
|
||||
0x9609A88E,
|
||||
0xE10E9818,
|
||||
0x7F6A0DBB,
|
||||
0x086D3D2D,
|
||||
0x91646C97,
|
||||
0xE6635C01,
|
||||
0x6B6B51F4,
|
||||
0x1C6C6162,
|
||||
0x856530D8,
|
||||
0xF262004E,
|
||||
0x6C0695ED,
|
||||
0x1B01A57B,
|
||||
0x8208F4C1,
|
||||
0xF50FC457,
|
||||
0x65B0D9C6,
|
||||
0x12B7E950,
|
||||
0x8BBEB8EA,
|
||||
0xFCB9887C,
|
||||
0x62DD1DDF,
|
||||
0x15DA2D49,
|
||||
0x8CD37CF3,
|
||||
0xFBD44C65,
|
||||
0x4DB26158,
|
||||
0x3AB551CE,
|
||||
0xA3BC0074,
|
||||
0xD4BB30E2,
|
||||
0x4ADFA541,
|
||||
0x3DD895D7,
|
||||
0xA4D1C46D,
|
||||
0xD3D6F4FB,
|
||||
0x4369E96A,
|
||||
0x346ED9FC,
|
||||
0xAD678846,
|
||||
0xDA60B8D0,
|
||||
0x44042D73,
|
||||
0x33031DE5,
|
||||
0xAA0A4C5F,
|
||||
0xDD0D7CC9,
|
||||
0x5005713C,
|
||||
0x270241AA,
|
||||
0xBE0B1010,
|
||||
0xC90C2086,
|
||||
0x5768B525,
|
||||
0x206F85B3,
|
||||
0xB966D409,
|
||||
0xCE61E49F,
|
||||
0x5EDEF90E,
|
||||
0x29D9C998,
|
||||
0xB0D09822,
|
||||
0xC7D7A8B4,
|
||||
0x59B33D17,
|
||||
0x2EB40D81,
|
||||
0xB7BD5C3B,
|
||||
0xC0BA6CAD,
|
||||
0xEDB88320,
|
||||
0x9ABFB3B6,
|
||||
0x03B6E20C,
|
||||
0x74B1D29A,
|
||||
0xEAD54739,
|
||||
0x9DD277AF,
|
||||
0x04DB2615,
|
||||
0x73DC1683,
|
||||
0xE3630B12,
|
||||
0x94643B84,
|
||||
0x0D6D6A3E,
|
||||
0x7A6A5AA8,
|
||||
0xE40ECF0B,
|
||||
0x9309FF9D,
|
||||
0x0A00AE27,
|
||||
0x7D079EB1,
|
||||
0xF00F9344,
|
||||
0x8708A3D2,
|
||||
0x1E01F268,
|
||||
0x6906C2FE,
|
||||
0xF762575D,
|
||||
0x806567CB,
|
||||
0x196C3671,
|
||||
0x6E6B06E7,
|
||||
0xFED41B76,
|
||||
0x89D32BE0,
|
||||
0x10DA7A5A,
|
||||
0x67DD4ACC,
|
||||
0xF9B9DF6F,
|
||||
0x8EBEEFF9,
|
||||
0x17B7BE43,
|
||||
0x60B08ED5,
|
||||
0xD6D6A3E8,
|
||||
0xA1D1937E,
|
||||
0x38D8C2C4,
|
||||
0x4FDFF252,
|
||||
0xD1BB67F1,
|
||||
0xA6BC5767,
|
||||
0x3FB506DD,
|
||||
0x48B2364B,
|
||||
0xD80D2BDA,
|
||||
0xAF0A1B4C,
|
||||
0x36034AF6,
|
||||
0x41047A60,
|
||||
0xDF60EFC3,
|
||||
0xA867DF55,
|
||||
0x316E8EEF,
|
||||
0x4669BE79,
|
||||
0xCB61B38C,
|
||||
0xBC66831A,
|
||||
0x256FD2A0,
|
||||
0x5268E236,
|
||||
0xCC0C7795,
|
||||
0xBB0B4703,
|
||||
0x220216B9,
|
||||
0x5505262F,
|
||||
0xC5BA3BBE,
|
||||
0xB2BD0B28,
|
||||
0x2BB45A92,
|
||||
0x5CB36A04,
|
||||
0xC2D7FFA7,
|
||||
0xB5D0CF31,
|
||||
0x2CD99E8B,
|
||||
0x5BDEAE1D,
|
||||
0x9B64C2B0,
|
||||
0xEC63F226,
|
||||
0x756AA39C,
|
||||
0x026D930A,
|
||||
0x9C0906A9,
|
||||
0xEB0E363F,
|
||||
0x72076785,
|
||||
0x05005713,
|
||||
0x95BF4A82,
|
||||
0xE2B87A14,
|
||||
0x7BB12BAE,
|
||||
0x0CB61B38,
|
||||
0x92D28E9B,
|
||||
0xE5D5BE0D,
|
||||
0x7CDCEFB7,
|
||||
0x0BDBDF21,
|
||||
0x86D3D2D4,
|
||||
0xF1D4E242,
|
||||
0x68DDB3F8,
|
||||
0x1FDA836E,
|
||||
0x81BE16CD,
|
||||
0xF6B9265B,
|
||||
0x6FB077E1,
|
||||
0x18B74777,
|
||||
0x88085AE6,
|
||||
0xFF0F6A70,
|
||||
0x66063BCA,
|
||||
0x11010B5C,
|
||||
0x8F659EFF,
|
||||
0xF862AE69,
|
||||
0x616BFFD3,
|
||||
0x166CCF45,
|
||||
0xA00AE278,
|
||||
0xD70DD2EE,
|
||||
0x4E048354,
|
||||
0x3903B3C2,
|
||||
0xA7672661,
|
||||
0xD06016F7,
|
||||
0x4969474D,
|
||||
0x3E6E77DB,
|
||||
0xAED16A4A,
|
||||
0xD9D65ADC,
|
||||
0x40DF0B66,
|
||||
0x37D83BF0,
|
||||
0xA9BCAE53,
|
||||
0xDEBB9EC5,
|
||||
0x47B2CF7F,
|
||||
0x30B5FFE9,
|
||||
0xBDBDF21C,
|
||||
0xCABAC28A,
|
||||
0x53B39330,
|
||||
0x24B4A3A6,
|
||||
0xBAD03605,
|
||||
0xCDD70693,
|
||||
0x54DE5729,
|
||||
0x23D967BF,
|
||||
0xB3667A2E,
|
||||
0xC4614AB8,
|
||||
0x5D681B02,
|
||||
0x2A6F2B94,
|
||||
0xB40BBE37,
|
||||
0xC30C8EA1,
|
||||
0x5A05DF1B,
|
||||
0x2D02EF8D
|
||||
};
|
||||
|
||||
UINT32 VtoyCrc32(VOID *Buffer, UINT32 Length)
|
||||
{
|
||||
UINT32 i;
|
||||
UINT8 *Ptr = Buffer;
|
||||
UINT32 Crc = 0xFFFFFFFF;
|
||||
|
||||
for (i = 0; i < Length; i++, Ptr++)
|
||||
{
|
||||
Crc = (Crc >> 8) ^ g_crc_table[(UINT8) Crc ^ *Ptr];
|
||||
}
|
||||
|
||||
return Crc ^ 0xffffffff;
|
||||
}
|
||||
|
35
vtoycli/fat_io_lib/buildlib.sh
Normal file
35
vtoycli/fat_io_lib/buildlib.sh
Normal file
@@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -rf include
|
||||
rm -rf lib
|
||||
|
||||
cd release
|
||||
#/opt/diet64/bin/diet -Os gcc -O2 -D_FILE_OFFSET_BITS=64 fat*.c -c
|
||||
gcc -specs "/usr/local/musl/lib/musl-gcc.specs" -O2 -D_FILE_OFFSET_BITS=64 fat*.c -c
|
||||
ar -rc libfat_io_64.a *.o
|
||||
rm -f *.o
|
||||
|
||||
|
||||
gcc -m32 -O2 -D_FILE_OFFSET_BITS=64 fat*.c -c
|
||||
ar -rc libfat_io_32.a *.o
|
||||
rm -f *.o
|
||||
|
||||
|
||||
aarch64-linux-gnu-gcc -O2 -D_FILE_OFFSET_BITS=64 fat*.c -c
|
||||
ar -rc libfat_io_aa64.a *.o
|
||||
rm -f *.o
|
||||
|
||||
|
||||
mips64el-linux-musl-gcc -mips64r2 -mabi=64 -O2 -D_FILE_OFFSET_BITS=64 fat*.c -c
|
||||
ar -rc libfat_io_m64e.a *.o
|
||||
rm -f *.o
|
||||
|
||||
cd -
|
||||
|
||||
|
||||
mkdir lib
|
||||
mkdir include
|
||||
|
||||
mv release/*.a lib/
|
||||
cp -a release/*.h include/
|
||||
|
133
vtoycli/fat_io_lib/include/fat_access.h
Normal file
133
vtoycli/fat_io_lib/include/fat_access.h
Normal file
@@ -0,0 +1,133 @@
|
||||
#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
|
13
vtoycli/fat_io_lib/include/fat_cache.h
Normal file
13
vtoycli/fat_io_lib/include/fat_cache.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#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
|
128
vtoycli/fat_io_lib/include/fat_defs.h
Normal file
128
vtoycli/fat_io_lib/include/fat_defs.h
Normal file
@@ -0,0 +1,128 @@
|
||||
#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
|
146
vtoycli/fat_io_lib/include/fat_filelib.h
Normal file
146
vtoycli/fat_io_lib/include/fat_filelib.h
Normal file
@@ -0,0 +1,146 @@
|
||||
#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
|
15
vtoycli/fat_io_lib/include/fat_format.h
Normal file
15
vtoycli/fat_io_lib/include/fat_format.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#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
|
161
vtoycli/fat_io_lib/include/fat_list.h
Normal file
161
vtoycli/fat_io_lib/include/fat_list.h
Normal file
@@ -0,0 +1,161 @@
|
||||
#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
|
||||
|
63
vtoycli/fat_io_lib/include/fat_misc.h
Normal file
63
vtoycli/fat_io_lib/include/fat_misc.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef __FAT_MISC_H__
|
||||
#define __FAT_MISC_H__
|
||||
|
||||
#include "fat_defs.h"
|
||||
#include "fat_opts.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
//-----------------------------------------------------------------------------
|
||||
#define MAX_LONGFILENAME_ENTRIES 20
|
||||
#define MAX_LFN_ENTRY_LENGTH 13
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Macros
|
||||
//-----------------------------------------------------------------------------
|
||||
#define GET_32BIT_WORD(buffer, location) ( ((uint32)buffer[location+3]<<24) + ((uint32)buffer[location+2]<<16) + ((uint32)buffer[location+1]<<8) + (uint32)buffer[location+0] )
|
||||
#define GET_16BIT_WORD(buffer, location) ( ((uint16)buffer[location+1]<<8) + (uint16)buffer[location+0] )
|
||||
|
||||
#define SET_32BIT_WORD(buffer, location, value) { buffer[location+0] = (uint8)((value)&0xFF); \
|
||||
buffer[location+1] = (uint8)((value>>8)&0xFF); \
|
||||
buffer[location+2] = (uint8)((value>>16)&0xFF); \
|
||||
buffer[location+3] = (uint8)((value>>24)&0xFF); }
|
||||
|
||||
#define SET_16BIT_WORD(buffer, location, value) { buffer[location+0] = (uint8)((value)&0xFF); \
|
||||
buffer[location+1] = (uint8)((value>>8)&0xFF); }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Structures
|
||||
//-----------------------------------------------------------------------------
|
||||
struct lfn_cache
|
||||
{
|
||||
#if FATFS_INC_LFN_SUPPORT
|
||||
// Long File Name Structure (max 260 LFN length)
|
||||
uint8 String[MAX_LONGFILENAME_ENTRIES][MAX_LFN_ENTRY_LENGTH];
|
||||
uint8 Null;
|
||||
#endif
|
||||
uint8 no_of_strings;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Prototypes
|
||||
//-----------------------------------------------------------------------------
|
||||
void fatfs_lfn_cache_init(struct lfn_cache *lfn, int wipeTable);
|
||||
void fatfs_lfn_cache_entry(struct lfn_cache *lfn, uint8 *entryBuffer);
|
||||
char* fatfs_lfn_cache_get(struct lfn_cache *lfn);
|
||||
int fatfs_entry_lfn_text(struct fat_dir_entry *entry);
|
||||
int fatfs_entry_lfn_invalid(struct fat_dir_entry *entry);
|
||||
int fatfs_entry_lfn_exists(struct lfn_cache *lfn, struct fat_dir_entry *entry);
|
||||
int fatfs_entry_sfn_only(struct fat_dir_entry *entry);
|
||||
int fatfs_entry_is_dir(struct fat_dir_entry *entry);
|
||||
int fatfs_entry_is_file(struct fat_dir_entry *entry);
|
||||
int fatfs_lfn_entries_required(char *filename);
|
||||
void fatfs_filename_to_lfn(char *filename, uint8 *buffer, int entry, uint8 sfnChk);
|
||||
void fatfs_sfn_create_entry(char *shortfilename, uint32 size, uint32 startCluster, struct fat_dir_entry *entry, int dir);
|
||||
int fatfs_lfn_create_sfn(char *sfn_output, char *filename);
|
||||
int fatfs_lfn_generate_tail(char *sfn_output, char *sfn_input, uint32 tailNum);
|
||||
void fatfs_convert_from_fat_time(uint16 fat_time, int *hours, int *minutes, int *seconds);
|
||||
void fatfs_convert_from_fat_date(uint16 fat_date, int *day, int *month, int *year);
|
||||
uint16 fatfs_convert_to_fat_time(int hours, int minutes, int seconds);
|
||||
uint16 fatfs_convert_to_fat_date(int day, int month, int year);
|
||||
void fatfs_print_sector(uint32 sector, uint8 *data);
|
||||
|
||||
#endif
|
90
vtoycli/fat_io_lib/include/fat_opts.h
Normal file
90
vtoycli/fat_io_lib/include/fat_opts.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef __FAT_OPTS_H__
|
||||
#define __FAT_OPTS_H__
|
||||
|
||||
#ifdef FATFS_USE_CUSTOM_OPTS_FILE
|
||||
#include "fat_custom.h"
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// Configuration
|
||||
//-------------------------------------------------------------
|
||||
|
||||
// Is the processor little endian (1) or big endian (0)
|
||||
#ifndef FATFS_IS_LITTLE_ENDIAN
|
||||
#define FATFS_IS_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
|
||||
// Max filename Length
|
||||
#ifndef FATFS_MAX_LONG_FILENAME
|
||||
#define FATFS_MAX_LONG_FILENAME 260
|
||||
#endif
|
||||
|
||||
// Max open files (reduce to lower memory requirements)
|
||||
#ifndef FATFS_MAX_OPEN_FILES
|
||||
#define FATFS_MAX_OPEN_FILES 2
|
||||
#endif
|
||||
|
||||
// Number of sectors per FAT_BUFFER (min 1)
|
||||
#ifndef FAT_BUFFER_SECTORS
|
||||
#define FAT_BUFFER_SECTORS 1
|
||||
#endif
|
||||
|
||||
// Max FAT sectors to buffer (min 1)
|
||||
// (mem used is FAT_BUFFERS * FAT_BUFFER_SECTORS * FAT_SECTOR_SIZE)
|
||||
#ifndef FAT_BUFFERS
|
||||
#define FAT_BUFFERS 1
|
||||
#endif
|
||||
|
||||
// Size of cluster chain cache (can be undefined)
|
||||
// Mem used = FAT_CLUSTER_CACHE_ENTRIES * 4 * 2
|
||||
// Improves access speed considerably
|
||||
//#define FAT_CLUSTER_CACHE_ENTRIES 128
|
||||
|
||||
// Include support for writing files (1 / 0)?
|
||||
#ifndef FATFS_INC_WRITE_SUPPORT
|
||||
#define FATFS_INC_WRITE_SUPPORT 1
|
||||
#endif
|
||||
|
||||
// Support long filenames (1 / 0)?
|
||||
// (if not (0) only 8.3 format is supported)
|
||||
#ifndef FATFS_INC_LFN_SUPPORT
|
||||
#define FATFS_INC_LFN_SUPPORT 1
|
||||
#endif
|
||||
|
||||
// Support directory listing (1 / 0)?
|
||||
#ifndef FATFS_DIR_LIST_SUPPORT
|
||||
#define FATFS_DIR_LIST_SUPPORT 1
|
||||
#endif
|
||||
|
||||
// Support time/date (1 / 0)?
|
||||
#ifndef FATFS_INC_TIME_DATE_SUPPORT
|
||||
#define FATFS_INC_TIME_DATE_SUPPORT 0
|
||||
#endif
|
||||
|
||||
// Include support for formatting disks (1 / 0)?
|
||||
#ifndef FATFS_INC_FORMAT_SUPPORT
|
||||
#define FATFS_INC_FORMAT_SUPPORT 1
|
||||
#endif
|
||||
|
||||
// Sector size used
|
||||
#define FAT_SECTOR_SIZE 512
|
||||
|
||||
// Printf output (directory listing / debug)
|
||||
#ifndef FAT_PRINTF
|
||||
// Don't include stdio, but there is a printf function available
|
||||
#ifdef FAT_PRINTF_NOINC_STDIO
|
||||
extern int printf(const char* ctrl1, ... );
|
||||
#define FAT_PRINTF(a) printf a
|
||||
// Include stdio to use printf
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#define FAT_PRINTF(a) printf a
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Time/Date support requires time.h
|
||||
#if FATFS_INC_TIME_DATE_SUPPORT
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#endif
|
20
vtoycli/fat_io_lib/include/fat_string.h
Normal file
20
vtoycli/fat_io_lib/include/fat_string.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef __FILESTRING_H__
|
||||
#define __FILESTRING_H__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Prototypes
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_total_path_levels(char *path);
|
||||
int fatfs_get_substring(char *Path, int levelreq, char *output, int max_len);
|
||||
int fatfs_split_path(char *FullPath, char *Path, int max_path, char *FileName, int max_filename);
|
||||
int fatfs_compare_names(char* strA, char* strB);
|
||||
int fatfs_string_ends_with_slash(char *path);
|
||||
int fatfs_get_sfn_display_name(char* out, char* in);
|
||||
int fatfs_get_extension(char* filename, char* out, int maxlen);
|
||||
int fatfs_create_path_string(char* path, char *filename, char* out, int maxlen);
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#endif
|
20
vtoycli/fat_io_lib/include/fat_table.h
Normal file
20
vtoycli/fat_io_lib/include/fat_table.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef __FAT_TABLE_H__
|
||||
#define __FAT_TABLE_H__
|
||||
|
||||
#include "fat_opts.h"
|
||||
#include "fat_misc.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Prototypes
|
||||
//-----------------------------------------------------------------------------
|
||||
void fatfs_fat_init(struct fatfs *fs);
|
||||
int fatfs_fat_purge(struct fatfs *fs);
|
||||
uint32 fatfs_find_next_cluster(struct fatfs *fs, uint32 current_cluster);
|
||||
void fatfs_set_fs_info_next_free_cluster(struct fatfs *fs, uint32 newValue);
|
||||
int fatfs_find_blank_cluster(struct fatfs *fs, uint32 start_cluster, uint32 *free_cluster);
|
||||
int fatfs_fat_set_cluster(struct fatfs *fs, uint32 cluster, uint32 next_cluster);
|
||||
int fatfs_fat_add_cluster_to_chain(struct fatfs *fs, uint32 start_cluster, uint32 newEntry);
|
||||
int fatfs_free_cluster_chain(struct fatfs *fs, uint32 start_cluster);
|
||||
uint32 fatfs_count_free_clusters(struct fatfs *fs);
|
||||
|
||||
#endif
|
69
vtoycli/fat_io_lib/include/fat_types.h
Normal file
69
vtoycli/fat_io_lib/include/fat_types.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#ifndef __FAT_TYPES_H__
|
||||
#define __FAT_TYPES_H__
|
||||
|
||||
// Detect 64-bit compilation on GCC
|
||||
#if defined(__GNUC__) && defined(__SIZEOF_LONG__)
|
||||
#if __SIZEOF_LONG__ == 8
|
||||
#define FATFS_DEF_UINT32_AS_INT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// System specific types
|
||||
//-------------------------------------------------------------
|
||||
#ifndef FATFS_NO_DEF_TYPES
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
|
||||
// If compiling on a 64-bit machine, use int as 32-bits
|
||||
#ifdef FATFS_DEF_UINT32_AS_INT
|
||||
typedef unsigned int uint32;
|
||||
// Else for 32-bit machines & embedded systems, use long...
|
||||
#else
|
||||
typedef unsigned long uint32;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// Endian Macros
|
||||
//-------------------------------------------------------------
|
||||
// FAT is little endian so big endian systems need to swap words
|
||||
|
||||
// Little Endian - No swap required
|
||||
#if FATFS_IS_LITTLE_ENDIAN == 1
|
||||
|
||||
#define FAT_HTONS(n) (n)
|
||||
#define FAT_HTONL(n) (n)
|
||||
|
||||
// Big Endian - Swap required
|
||||
#else
|
||||
|
||||
#define FAT_HTONS(n) ((((uint16)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8))
|
||||
#define FAT_HTONL(n) (((((uint32)(n) & 0xFF)) << 24) | \
|
||||
((((uint32)(n) & 0xFF00)) << 8) | \
|
||||
((((uint32)(n) & 0xFF0000)) >> 8) | \
|
||||
((((uint32)(n) & 0xFF000000)) >> 24))
|
||||
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// Structure Packing Compile Options
|
||||
//-------------------------------------------------------------
|
||||
#ifdef __GNUC__
|
||||
#define STRUCT_PACK
|
||||
#define STRUCT_PACK_BEGIN
|
||||
#define STRUCT_PACK_END
|
||||
#define STRUCT_PACKED __attribute__ ((packed))
|
||||
#else
|
||||
// Other compilers may require other methods of packing structures
|
||||
#define STRUCT_PACK
|
||||
#define STRUCT_PACK_BEGIN
|
||||
#define STRUCT_PACK_END
|
||||
#define STRUCT_PACKED
|
||||
#endif
|
||||
|
||||
#endif
|
14
vtoycli/fat_io_lib/include/fat_write.h
Normal file
14
vtoycli/fat_io_lib/include/fat_write.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef __FAT_WRITE_H__
|
||||
#define __FAT_WRITE_H__
|
||||
|
||||
#include "fat_defs.h"
|
||||
#include "fat_opts.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Prototypes
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_add_file_entry(struct fatfs *fs, uint32 dirCluster, char *filename, char *shortfilename, uint32 startCluster, uint32 size, int dir);
|
||||
int fatfs_add_free_space(struct fatfs *fs, uint32 *startCluster, uint32 clusters);
|
||||
int fatfs_allocate_free_space(struct fatfs *fs, int newFile, uint32 *startCluster, uint32 size);
|
||||
|
||||
#endif
|
BIN
vtoycli/fat_io_lib/lib/libfat_io_32.a
Normal file
BIN
vtoycli/fat_io_lib/lib/libfat_io_32.a
Normal file
Binary file not shown.
BIN
vtoycli/fat_io_lib/lib/libfat_io_64.a
Normal file
BIN
vtoycli/fat_io_lib/lib/libfat_io_64.a
Normal file
Binary file not shown.
BIN
vtoycli/fat_io_lib/lib/libfat_io_aa64.a
Normal file
BIN
vtoycli/fat_io_lib/lib/libfat_io_aa64.a
Normal file
Binary file not shown.
BIN
vtoycli/fat_io_lib/lib/libfat_io_m64e.a
Normal file
BIN
vtoycli/fat_io_lib/lib/libfat_io_m64e.a
Normal file
Binary file not shown.
22
vtoycli/fat_io_lib/release/API.txt
Normal file
22
vtoycli/fat_io_lib/release/API.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
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 <20>locked<65> 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.
|
345
vtoycli/fat_io_lib/release/COPYRIGHT.txt
Normal file
345
vtoycli/fat_io_lib/release/COPYRIGHT.txt
Normal file
@@ -0,0 +1,345 @@
|
||||
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.
|
53
vtoycli/fat_io_lib/release/Configuration.txt
Normal file
53
vtoycli/fat_io_lib/release/Configuration.txt
Normal file
@@ -0,0 +1,53 @@
|
||||
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
|
24
vtoycli/fat_io_lib/release/History.txt
Normal file
24
vtoycli/fat_io_lib/release/History.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
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 <20> Massive read + write performance improvements.
|
||||
V2.6.5 <20> Bug fixes for big endian systems.
|
||||
V2.6.4 <20> Further bug fixes and performance improvements for write operations.
|
||||
V2.6.3 <20> 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.
|
10
vtoycli/fat_io_lib/release/License.txt
Normal file
10
vtoycli/fat_io_lib/release/License.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
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
|
40
vtoycli/fat_io_lib/release/Media Access API.txt
Normal file
40
vtoycli/fat_io_lib/release/Media Access API.txt
Normal file
@@ -0,0 +1,40 @@
|
||||
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)
|
||||
|
||||
|
||||
|
87
vtoycli/fat_io_lib/release/example.c
Normal file
87
vtoycli/fat_io_lib/release/example.c
Normal file
@@ -0,0 +1,87 @@
|
||||
#include <stdio.h>
|
||||
#include "fat_filelib.h"
|
||||
|
||||
int media_init()
|
||||
{
|
||||
// ...
|
||||
return 1;
|
||||
}
|
||||
|
||||
int media_read(unsigned long sector, unsigned char *buffer, unsigned long sector_count)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
for (i=0;i<sector_count;i++)
|
||||
{
|
||||
// ...
|
||||
// Add platform specific sector (512 bytes) read code here
|
||||
//..
|
||||
|
||||
sector ++;
|
||||
buffer += 512;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int media_write(unsigned long sector, unsigned char *buffer, unsigned long sector_count)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
for (i=0;i<sector_count;i++)
|
||||
{
|
||||
// ...
|
||||
// Add platform specific sector (512 bytes) write code here
|
||||
//..
|
||||
|
||||
sector ++;
|
||||
buffer += 512;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
FL_FILE *file;
|
||||
|
||||
// Initialise media
|
||||
media_init();
|
||||
|
||||
// Initialise File IO Library
|
||||
fl_init();
|
||||
|
||||
// Attach media access functions to library
|
||||
if (fl_attach_media(media_read, media_write) != FAT_INIT_OK)
|
||||
{
|
||||
printf("ERROR: Media attach failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// List root directory
|
||||
fl_listdirectory("/");
|
||||
|
||||
// Create File
|
||||
file = fl_fopen("/file.bin", "w");
|
||||
if (file)
|
||||
{
|
||||
// Write some data
|
||||
unsigned char data[] = { 1, 2, 3, 4 };
|
||||
if (fl_fwrite(data, 1, sizeof(data), file) != sizeof(data))
|
||||
printf("ERROR: Write file failed\n");
|
||||
}
|
||||
else
|
||||
printf("ERROR: Create file failed\n");
|
||||
|
||||
// Close file
|
||||
fl_fclose(file);
|
||||
|
||||
// Delete File
|
||||
if (fl_remove("/file.bin") < 0)
|
||||
printf("ERROR: Delete file failed\n");
|
||||
|
||||
// List root directory
|
||||
fl_listdirectory("/");
|
||||
|
||||
fl_shutdown();
|
||||
}
|
904
vtoycli/fat_io_lib/release/fat_access.c
Normal file
904
vtoycli/fat_io_lib/release/fat_access.c
Normal file
@@ -0,0 +1,904 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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);
|
||||
strncpy(entry->filename, long_filename, FATFS_MAX_LONG_FILENAME-1);
|
||||
|
||||
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
|
133
vtoycli/fat_io_lib/release/fat_access.h
Normal file
133
vtoycli/fat_io_lib/release/fat_access.h
Normal file
@@ -0,0 +1,133 @@
|
||||
#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
|
91
vtoycli/fat_io_lib/release/fat_cache.c
Normal file
91
vtoycli/fat_io_lib/release/fat_cache.c
Normal file
@@ -0,0 +1,91 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
13
vtoycli/fat_io_lib/release/fat_cache.h
Normal file
13
vtoycli/fat_io_lib/release/fat_cache.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#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
|
128
vtoycli/fat_io_lib/release/fat_defs.h
Normal file
128
vtoycli/fat_io_lib/release/fat_defs.h
Normal file
@@ -0,0 +1,128 @@
|
||||
#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
|
1603
vtoycli/fat_io_lib/release/fat_filelib.c
Normal file
1603
vtoycli/fat_io_lib/release/fat_filelib.c
Normal file
File diff suppressed because it is too large
Load Diff
146
vtoycli/fat_io_lib/release/fat_filelib.h
Normal file
146
vtoycli/fat_io_lib/release/fat_filelib.h
Normal file
@@ -0,0 +1,146 @@
|
||||
#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
|
532
vtoycli/fat_io_lib/release/fat_format.c
Normal file
532
vtoycli/fat_io_lib/release/fat_format.c
Normal file
@@ -0,0 +1,532 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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*/
|
15
vtoycli/fat_io_lib/release/fat_format.h
Normal file
15
vtoycli/fat_io_lib/release/fat_format.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#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
|
161
vtoycli/fat_io_lib/release/fat_list.h
Normal file
161
vtoycli/fat_io_lib/release/fat_list.h
Normal file
@@ -0,0 +1,161 @@
|
||||
#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
|
||||
|
505
vtoycli/fat_io_lib/release/fat_misc.c
Normal file
505
vtoycli/fat_io_lib/release/fat_misc.c
Normal file
@@ -0,0 +1,505 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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_misc.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_lfn_cache_init: Clear long file name cache
|
||||
//-----------------------------------------------------------------------------
|
||||
void fatfs_lfn_cache_init(struct lfn_cache *lfn, int wipeTable)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
lfn->no_of_strings = 0;
|
||||
|
||||
#if FATFS_INC_LFN_SUPPORT
|
||||
|
||||
// Zero out buffer also
|
||||
if (wipeTable)
|
||||
for (i=0;i<MAX_LONGFILENAME_ENTRIES;i++)
|
||||
memset(lfn->String[i], 0x00, MAX_LFN_ENTRY_LENGTH);
|
||||
#endif
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_lfn_cache_entry - Function extracts long file name text from sector
|
||||
// at a specific offset
|
||||
//-----------------------------------------------------------------------------
|
||||
#if FATFS_INC_LFN_SUPPORT
|
||||
void fatfs_lfn_cache_entry(struct lfn_cache *lfn, uint8 *entryBuffer)
|
||||
{
|
||||
uint8 LFNIndex, i;
|
||||
LFNIndex = entryBuffer[0] & 0x1F;
|
||||
|
||||
// Limit file name to cache size!
|
||||
if (LFNIndex > MAX_LONGFILENAME_ENTRIES)
|
||||
return ;
|
||||
|
||||
// This is an error condition
|
||||
if (LFNIndex == 0)
|
||||
return ;
|
||||
|
||||
if (lfn->no_of_strings == 0)
|
||||
lfn->no_of_strings = LFNIndex;
|
||||
|
||||
lfn->String[LFNIndex-1][0] = entryBuffer[1];
|
||||
lfn->String[LFNIndex-1][1] = entryBuffer[3];
|
||||
lfn->String[LFNIndex-1][2] = entryBuffer[5];
|
||||
lfn->String[LFNIndex-1][3] = entryBuffer[7];
|
||||
lfn->String[LFNIndex-1][4] = entryBuffer[9];
|
||||
lfn->String[LFNIndex-1][5] = entryBuffer[0x0E];
|
||||
lfn->String[LFNIndex-1][6] = entryBuffer[0x10];
|
||||
lfn->String[LFNIndex-1][7] = entryBuffer[0x12];
|
||||
lfn->String[LFNIndex-1][8] = entryBuffer[0x14];
|
||||
lfn->String[LFNIndex-1][9] = entryBuffer[0x16];
|
||||
lfn->String[LFNIndex-1][10] = entryBuffer[0x18];
|
||||
lfn->String[LFNIndex-1][11] = entryBuffer[0x1C];
|
||||
lfn->String[LFNIndex-1][12] = entryBuffer[0x1E];
|
||||
|
||||
for (i=0; i<MAX_LFN_ENTRY_LENGTH; i++)
|
||||
if (lfn->String[LFNIndex-1][i]==0xFF)
|
||||
lfn->String[LFNIndex-1][i] = 0x20; // Replace with spaces
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_lfn_cache_get: Get a reference to the long filename
|
||||
//-----------------------------------------------------------------------------
|
||||
#if FATFS_INC_LFN_SUPPORT
|
||||
char* fatfs_lfn_cache_get(struct lfn_cache *lfn)
|
||||
{
|
||||
// Null terminate long filename
|
||||
if (lfn->no_of_strings == MAX_LONGFILENAME_ENTRIES)
|
||||
lfn->Null = '\0';
|
||||
else if (lfn->no_of_strings)
|
||||
lfn->String[lfn->no_of_strings][0] = '\0';
|
||||
else
|
||||
lfn->String[0][0] = '\0';
|
||||
|
||||
return (char*)&lfn->String[0][0];
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_entry_lfn_text: If LFN text entry found
|
||||
//-----------------------------------------------------------------------------
|
||||
#if FATFS_INC_LFN_SUPPORT
|
||||
int fatfs_entry_lfn_text(struct fat_dir_entry *entry)
|
||||
{
|
||||
if ((entry->Attr & FILE_ATTR_LFN_TEXT) == FILE_ATTR_LFN_TEXT)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_entry_lfn_invalid: If SFN found not relating to LFN
|
||||
//-----------------------------------------------------------------------------
|
||||
#if FATFS_INC_LFN_SUPPORT
|
||||
int fatfs_entry_lfn_invalid(struct fat_dir_entry *entry)
|
||||
{
|
||||
if ( (entry->Name[0]==FILE_HEADER_BLANK) ||
|
||||
(entry->Name[0]==FILE_HEADER_DELETED)||
|
||||
(entry->Attr==FILE_ATTR_VOLUME_ID) ||
|
||||
(entry->Attr & FILE_ATTR_SYSHID) )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_entry_lfn_exists: If LFN exists and correlation SFN found
|
||||
//-----------------------------------------------------------------------------
|
||||
#if FATFS_INC_LFN_SUPPORT
|
||||
int fatfs_entry_lfn_exists(struct lfn_cache *lfn, struct fat_dir_entry *entry)
|
||||
{
|
||||
if ( (entry->Attr!=FILE_ATTR_LFN_TEXT) &&
|
||||
(entry->Name[0]!=FILE_HEADER_BLANK) &&
|
||||
(entry->Name[0]!=FILE_HEADER_DELETED) &&
|
||||
(entry->Attr!=FILE_ATTR_VOLUME_ID) &&
|
||||
(!(entry->Attr&FILE_ATTR_SYSHID)) &&
|
||||
(lfn->no_of_strings) )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_entry_sfn_only: If SFN only exists
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_entry_sfn_only(struct fat_dir_entry *entry)
|
||||
{
|
||||
if ( (entry->Attr!=FILE_ATTR_LFN_TEXT) &&
|
||||
(entry->Name[0]!=FILE_HEADER_BLANK) &&
|
||||
(entry->Name[0]!=FILE_HEADER_DELETED) &&
|
||||
(entry->Attr!=FILE_ATTR_VOLUME_ID) &&
|
||||
(!(entry->Attr&FILE_ATTR_SYSHID)) )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
// TODO: FILE_ATTR_SYSHID ?!?!??!
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_entry_is_dir: Returns 1 if a directory
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_entry_is_dir(struct fat_dir_entry *entry)
|
||||
{
|
||||
if (entry->Attr & FILE_TYPE_DIR)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_entry_is_file: Returns 1 is a file entry
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_entry_is_file(struct fat_dir_entry *entry)
|
||||
{
|
||||
if (entry->Attr & FILE_TYPE_FILE)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_lfn_entries_required: Calculate number of 13 characters entries
|
||||
//-----------------------------------------------------------------------------
|
||||
#if FATFS_INC_LFN_SUPPORT
|
||||
int fatfs_lfn_entries_required(char *filename)
|
||||
{
|
||||
int length = (int)strlen(filename);
|
||||
|
||||
if (length)
|
||||
return (length + MAX_LFN_ENTRY_LENGTH - 1) / MAX_LFN_ENTRY_LENGTH;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_filename_to_lfn:
|
||||
//-----------------------------------------------------------------------------
|
||||
#if FATFS_INC_LFN_SUPPORT
|
||||
void fatfs_filename_to_lfn(char *filename, uint8 *buffer, int entry, uint8 sfnChk)
|
||||
{
|
||||
int i;
|
||||
int nameIndexes[MAX_LFN_ENTRY_LENGTH] = {1,3,5,7,9,0x0E,0x10,0x12,0x14,0x16,0x18,0x1C,0x1E};
|
||||
|
||||
// 13 characters entries
|
||||
int length = (int)strlen(filename);
|
||||
int entriesRequired = fatfs_lfn_entries_required(filename);
|
||||
|
||||
// Filename offset
|
||||
int start = entry * MAX_LFN_ENTRY_LENGTH;
|
||||
|
||||
// Initialise to zeros
|
||||
memset(buffer, 0x00, FAT_DIR_ENTRY_SIZE);
|
||||
|
||||
// LFN entry number
|
||||
buffer[0] = (uint8)(((entriesRequired-1)==entry)?(0x40|(entry+1)):(entry+1));
|
||||
|
||||
// LFN flag
|
||||
buffer[11] = 0x0F;
|
||||
|
||||
// Checksum of short filename
|
||||
buffer[13] = sfnChk;
|
||||
|
||||
// Copy to buffer
|
||||
for (i=0;i<MAX_LFN_ENTRY_LENGTH;i++)
|
||||
{
|
||||
if ( (start+i) < length )
|
||||
buffer[nameIndexes[i]] = filename[start+i];
|
||||
else if ( (start+i) == length )
|
||||
buffer[nameIndexes[i]] = 0x00;
|
||||
else
|
||||
{
|
||||
buffer[nameIndexes[i]] = 0xFF;
|
||||
buffer[nameIndexes[i]+1] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_sfn_create_entry: Create the short filename directory entry
|
||||
//-----------------------------------------------------------------------------
|
||||
#if FATFS_INC_WRITE_SUPPORT
|
||||
void fatfs_sfn_create_entry(char *shortfilename, uint32 size, uint32 startCluster, struct fat_dir_entry *entry, int dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Copy short filename
|
||||
for (i=0;i<FAT_SFN_SIZE_FULL;i++)
|
||||
entry->Name[i] = shortfilename[i];
|
||||
|
||||
// Unless we have a RTC we might as well set these to 1980
|
||||
entry->CrtTimeTenth = 0x00;
|
||||
entry->CrtTime[1] = entry->CrtTime[0] = 0x00;
|
||||
entry->CrtDate[1] = 0x00;
|
||||
entry->CrtDate[0] = 0x20;
|
||||
entry->LstAccDate[1] = 0x00;
|
||||
entry->LstAccDate[0] = 0x20;
|
||||
entry->WrtTime[1] = entry->WrtTime[0] = 0x00;
|
||||
entry->WrtDate[1] = 0x00;
|
||||
entry->WrtDate[0] = 0x20;
|
||||
|
||||
if (!dir)
|
||||
entry->Attr = FILE_TYPE_FILE;
|
||||
else
|
||||
entry->Attr = FILE_TYPE_DIR;
|
||||
|
||||
entry->NTRes = 0x00;
|
||||
|
||||
entry->FstClusHI = FAT_HTONS((uint16)((startCluster>>16) & 0xFFFF));
|
||||
entry->FstClusLO = FAT_HTONS((uint16)((startCluster>>0) & 0xFFFF));
|
||||
entry->FileSize = FAT_HTONL(size);
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_lfn_create_sfn: Create a padded SFN
|
||||
//-----------------------------------------------------------------------------
|
||||
#if FATFS_INC_WRITE_SUPPORT
|
||||
int fatfs_lfn_create_sfn(char *sfn_output, char *filename)
|
||||
{
|
||||
int i;
|
||||
int dotPos = -1;
|
||||
char ext[3];
|
||||
int pos;
|
||||
int len = (int)strlen(filename);
|
||||
|
||||
// Invalid to start with .
|
||||
if (filename[0]=='.')
|
||||
return 0;
|
||||
|
||||
memset(sfn_output, ' ', FAT_SFN_SIZE_FULL);
|
||||
memset(ext, ' ', 3);
|
||||
|
||||
// Find dot seperator
|
||||
for (i = 0; i< len; i++)
|
||||
{
|
||||
if (filename[i]=='.')
|
||||
dotPos = i;
|
||||
}
|
||||
|
||||
// Extract extensions
|
||||
if (dotPos!=-1)
|
||||
{
|
||||
// Copy first three chars of extension
|
||||
for (i = (dotPos+1); i < (dotPos+1+3); i++)
|
||||
if (i<len)
|
||||
ext[i-(dotPos+1)] = filename[i];
|
||||
|
||||
// Shorten the length to the dot position
|
||||
len = dotPos;
|
||||
}
|
||||
|
||||
// Add filename part
|
||||
pos = 0;
|
||||
for (i=0;i<len;i++)
|
||||
{
|
||||
if ( (filename[i]!=' ') && (filename[i]!='.') )
|
||||
{
|
||||
if (filename[i] >= 'a' && filename[i] <= 'z')
|
||||
sfn_output[pos++] = filename[i] - 'a' + 'A';
|
||||
else
|
||||
sfn_output[pos++] = filename[i];
|
||||
}
|
||||
|
||||
// Fill upto 8 characters
|
||||
if (pos==FAT_SFN_SIZE_PARTIAL)
|
||||
break;
|
||||
}
|
||||
|
||||
// Add extension part
|
||||
for (i=FAT_SFN_SIZE_PARTIAL;i<FAT_SFN_SIZE_FULL;i++)
|
||||
{
|
||||
if (ext[i-FAT_SFN_SIZE_PARTIAL] >= 'a' && ext[i-FAT_SFN_SIZE_PARTIAL] <= 'z')
|
||||
sfn_output[i] = ext[i-FAT_SFN_SIZE_PARTIAL] - 'a' + 'A';
|
||||
else
|
||||
sfn_output[i] = ext[i-FAT_SFN_SIZE_PARTIAL];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_itoa:
|
||||
//-----------------------------------------------------------------------------
|
||||
static void fatfs_itoa(uint32 num, char *s)
|
||||
{
|
||||
char* cp;
|
||||
char outbuf[12];
|
||||
const char digits[] = "0123456789ABCDEF";
|
||||
|
||||
// Build string backwards
|
||||
cp = outbuf;
|
||||
do
|
||||
{
|
||||
*cp++ = digits[(int)(num % 10)];
|
||||
}
|
||||
while ((num /= 10) > 0);
|
||||
|
||||
*cp-- = 0;
|
||||
|
||||
// Copy in forwards
|
||||
while (cp >= outbuf)
|
||||
*s++ = *cp--;
|
||||
|
||||
*s = 0;
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_lfn_generate_tail:
|
||||
// sfn_input = Input short filename, spaced format & in upper case
|
||||
// sfn_output = Output short filename with tail
|
||||
//-----------------------------------------------------------------------------
|
||||
#if FATFS_INC_LFN_SUPPORT
|
||||
#if FATFS_INC_WRITE_SUPPORT
|
||||
int fatfs_lfn_generate_tail(char *sfn_output, char *sfn_input, uint32 tailNum)
|
||||
{
|
||||
int tail_chars;
|
||||
char tail_str[12];
|
||||
|
||||
if (tailNum > 99999)
|
||||
return 0;
|
||||
|
||||
// Convert to number
|
||||
memset(tail_str, 0x00, sizeof(tail_str));
|
||||
tail_str[0] = '~';
|
||||
fatfs_itoa(tailNum, tail_str+1);
|
||||
|
||||
// Copy in base filename
|
||||
memcpy(sfn_output, sfn_input, FAT_SFN_SIZE_FULL);
|
||||
|
||||
// Overwrite with tail
|
||||
tail_chars = (int)strlen(tail_str);
|
||||
memcpy(sfn_output+(FAT_SFN_SIZE_PARTIAL-tail_chars), tail_str, tail_chars);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_convert_from_fat_time: Convert FAT time to h/m/s
|
||||
//-----------------------------------------------------------------------------
|
||||
#if FATFS_INC_TIME_DATE_SUPPORT
|
||||
void fatfs_convert_from_fat_time(uint16 fat_time, int *hours, int *minutes, int *seconds)
|
||||
{
|
||||
*hours = (fat_time >> FAT_TIME_HOURS_SHIFT) & FAT_TIME_HOURS_MASK;
|
||||
*minutes = (fat_time >> FAT_TIME_MINUTES_SHIFT) & FAT_TIME_MINUTES_MASK;
|
||||
*seconds = (fat_time >> FAT_TIME_SECONDS_SHIFT) & FAT_TIME_SECONDS_MASK;
|
||||
*seconds = *seconds * FAT_TIME_SECONDS_SCALE;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_convert_from_fat_date: Convert FAT date to d/m/y
|
||||
//-----------------------------------------------------------------------------
|
||||
void fatfs_convert_from_fat_date(uint16 fat_date, int *day, int *month, int *year)
|
||||
{
|
||||
*day = (fat_date >> FAT_DATE_DAY_SHIFT) & FAT_DATE_DAY_MASK;
|
||||
*month = (fat_date >> FAT_DATE_MONTH_SHIFT) & FAT_DATE_MONTH_MASK;
|
||||
*year = (fat_date >> FAT_DATE_YEAR_SHIFT) & FAT_DATE_YEAR_MASK;
|
||||
*year = *year + FAT_DATE_YEAR_OFFSET;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_convert_to_fat_time: Convert h/m/s to FAT time
|
||||
//-----------------------------------------------------------------------------
|
||||
uint16 fatfs_convert_to_fat_time(int hours, int minutes, int seconds)
|
||||
{
|
||||
uint16 fat_time = 0;
|
||||
|
||||
// Most FAT times are to a resolution of 2 seconds
|
||||
seconds /= FAT_TIME_SECONDS_SCALE;
|
||||
|
||||
fat_time = (hours & FAT_TIME_HOURS_MASK) << FAT_TIME_HOURS_SHIFT;
|
||||
fat_time|= (minutes & FAT_TIME_MINUTES_MASK) << FAT_TIME_MINUTES_SHIFT;
|
||||
fat_time|= (seconds & FAT_TIME_SECONDS_MASK) << FAT_TIME_SECONDS_SHIFT;
|
||||
|
||||
return fat_time;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_convert_to_fat_date: Convert d/m/y to FAT date
|
||||
//-----------------------------------------------------------------------------
|
||||
uint16 fatfs_convert_to_fat_date(int day, int month, int year)
|
||||
{
|
||||
uint16 fat_date = 0;
|
||||
|
||||
// FAT dates are relative to 1980
|
||||
if (year >= FAT_DATE_YEAR_OFFSET)
|
||||
year -= FAT_DATE_YEAR_OFFSET;
|
||||
|
||||
fat_date = (day & FAT_DATE_DAY_MASK) << FAT_DATE_DAY_SHIFT;
|
||||
fat_date|= (month & FAT_DATE_MONTH_MASK) << FAT_DATE_MONTH_SHIFT;
|
||||
fat_date|= (year & FAT_DATE_YEAR_MASK) << FAT_DATE_YEAR_SHIFT;
|
||||
|
||||
return fat_date;
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_print_sector:
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef FATFS_DEBUG
|
||||
void fatfs_print_sector(uint32 sector, uint8 *data)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
|
||||
FAT_PRINTF(("Sector %d:\n", sector));
|
||||
|
||||
for (i=0;i<FAT_SECTOR_SIZE;i++)
|
||||
{
|
||||
if (!((i) % 16))
|
||||
{
|
||||
FAT_PRINTF((" %04d: ", i));
|
||||
}
|
||||
|
||||
FAT_PRINTF(("%02x", data[i]));
|
||||
if (!((i+1) % 4))
|
||||
{
|
||||
FAT_PRINTF((" "));
|
||||
}
|
||||
|
||||
if (!((i+1) % 16))
|
||||
{
|
||||
FAT_PRINTF((" "));
|
||||
for (j=0;j<16;j++)
|
||||
{
|
||||
char ch = data[i-15+j];
|
||||
|
||||
// Is printable?
|
||||
if (ch > 31 && ch < 127)
|
||||
{
|
||||
FAT_PRINTF(("%c", ch));
|
||||
}
|
||||
else
|
||||
{
|
||||
FAT_PRINTF(("."));
|
||||
}
|
||||
}
|
||||
|
||||
FAT_PRINTF(("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
63
vtoycli/fat_io_lib/release/fat_misc.h
Normal file
63
vtoycli/fat_io_lib/release/fat_misc.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef __FAT_MISC_H__
|
||||
#define __FAT_MISC_H__
|
||||
|
||||
#include "fat_defs.h"
|
||||
#include "fat_opts.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
//-----------------------------------------------------------------------------
|
||||
#define MAX_LONGFILENAME_ENTRIES 20
|
||||
#define MAX_LFN_ENTRY_LENGTH 13
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Macros
|
||||
//-----------------------------------------------------------------------------
|
||||
#define GET_32BIT_WORD(buffer, location) ( ((uint32)buffer[location+3]<<24) + ((uint32)buffer[location+2]<<16) + ((uint32)buffer[location+1]<<8) + (uint32)buffer[location+0] )
|
||||
#define GET_16BIT_WORD(buffer, location) ( ((uint16)buffer[location+1]<<8) + (uint16)buffer[location+0] )
|
||||
|
||||
#define SET_32BIT_WORD(buffer, location, value) { buffer[location+0] = (uint8)((value)&0xFF); \
|
||||
buffer[location+1] = (uint8)((value>>8)&0xFF); \
|
||||
buffer[location+2] = (uint8)((value>>16)&0xFF); \
|
||||
buffer[location+3] = (uint8)((value>>24)&0xFF); }
|
||||
|
||||
#define SET_16BIT_WORD(buffer, location, value) { buffer[location+0] = (uint8)((value)&0xFF); \
|
||||
buffer[location+1] = (uint8)((value>>8)&0xFF); }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Structures
|
||||
//-----------------------------------------------------------------------------
|
||||
struct lfn_cache
|
||||
{
|
||||
#if FATFS_INC_LFN_SUPPORT
|
||||
// Long File Name Structure (max 260 LFN length)
|
||||
uint8 String[MAX_LONGFILENAME_ENTRIES][MAX_LFN_ENTRY_LENGTH];
|
||||
uint8 Null;
|
||||
#endif
|
||||
uint8 no_of_strings;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Prototypes
|
||||
//-----------------------------------------------------------------------------
|
||||
void fatfs_lfn_cache_init(struct lfn_cache *lfn, int wipeTable);
|
||||
void fatfs_lfn_cache_entry(struct lfn_cache *lfn, uint8 *entryBuffer);
|
||||
char* fatfs_lfn_cache_get(struct lfn_cache *lfn);
|
||||
int fatfs_entry_lfn_text(struct fat_dir_entry *entry);
|
||||
int fatfs_entry_lfn_invalid(struct fat_dir_entry *entry);
|
||||
int fatfs_entry_lfn_exists(struct lfn_cache *lfn, struct fat_dir_entry *entry);
|
||||
int fatfs_entry_sfn_only(struct fat_dir_entry *entry);
|
||||
int fatfs_entry_is_dir(struct fat_dir_entry *entry);
|
||||
int fatfs_entry_is_file(struct fat_dir_entry *entry);
|
||||
int fatfs_lfn_entries_required(char *filename);
|
||||
void fatfs_filename_to_lfn(char *filename, uint8 *buffer, int entry, uint8 sfnChk);
|
||||
void fatfs_sfn_create_entry(char *shortfilename, uint32 size, uint32 startCluster, struct fat_dir_entry *entry, int dir);
|
||||
int fatfs_lfn_create_sfn(char *sfn_output, char *filename);
|
||||
int fatfs_lfn_generate_tail(char *sfn_output, char *sfn_input, uint32 tailNum);
|
||||
void fatfs_convert_from_fat_time(uint16 fat_time, int *hours, int *minutes, int *seconds);
|
||||
void fatfs_convert_from_fat_date(uint16 fat_date, int *day, int *month, int *year);
|
||||
uint16 fatfs_convert_to_fat_time(int hours, int minutes, int seconds);
|
||||
uint16 fatfs_convert_to_fat_date(int day, int month, int year);
|
||||
void fatfs_print_sector(uint32 sector, uint8 *data);
|
||||
|
||||
#endif
|
90
vtoycli/fat_io_lib/release/fat_opts.h
Normal file
90
vtoycli/fat_io_lib/release/fat_opts.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef __FAT_OPTS_H__
|
||||
#define __FAT_OPTS_H__
|
||||
|
||||
#ifdef FATFS_USE_CUSTOM_OPTS_FILE
|
||||
#include "fat_custom.h"
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// Configuration
|
||||
//-------------------------------------------------------------
|
||||
|
||||
// Is the processor little endian (1) or big endian (0)
|
||||
#ifndef FATFS_IS_LITTLE_ENDIAN
|
||||
#define FATFS_IS_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
|
||||
// Max filename Length
|
||||
#ifndef FATFS_MAX_LONG_FILENAME
|
||||
#define FATFS_MAX_LONG_FILENAME 260
|
||||
#endif
|
||||
|
||||
// Max open files (reduce to lower memory requirements)
|
||||
#ifndef FATFS_MAX_OPEN_FILES
|
||||
#define FATFS_MAX_OPEN_FILES 2
|
||||
#endif
|
||||
|
||||
// Number of sectors per FAT_BUFFER (min 1)
|
||||
#ifndef FAT_BUFFER_SECTORS
|
||||
#define FAT_BUFFER_SECTORS 1
|
||||
#endif
|
||||
|
||||
// Max FAT sectors to buffer (min 1)
|
||||
// (mem used is FAT_BUFFERS * FAT_BUFFER_SECTORS * FAT_SECTOR_SIZE)
|
||||
#ifndef FAT_BUFFERS
|
||||
#define FAT_BUFFERS 1
|
||||
#endif
|
||||
|
||||
// Size of cluster chain cache (can be undefined)
|
||||
// Mem used = FAT_CLUSTER_CACHE_ENTRIES * 4 * 2
|
||||
// Improves access speed considerably
|
||||
//#define FAT_CLUSTER_CACHE_ENTRIES 128
|
||||
|
||||
// Include support for writing files (1 / 0)?
|
||||
#ifndef FATFS_INC_WRITE_SUPPORT
|
||||
#define FATFS_INC_WRITE_SUPPORT 1
|
||||
#endif
|
||||
|
||||
// Support long filenames (1 / 0)?
|
||||
// (if not (0) only 8.3 format is supported)
|
||||
#ifndef FATFS_INC_LFN_SUPPORT
|
||||
#define FATFS_INC_LFN_SUPPORT 1
|
||||
#endif
|
||||
|
||||
// Support directory listing (1 / 0)?
|
||||
#ifndef FATFS_DIR_LIST_SUPPORT
|
||||
#define FATFS_DIR_LIST_SUPPORT 1
|
||||
#endif
|
||||
|
||||
// Support time/date (1 / 0)?
|
||||
#ifndef FATFS_INC_TIME_DATE_SUPPORT
|
||||
#define FATFS_INC_TIME_DATE_SUPPORT 0
|
||||
#endif
|
||||
|
||||
// Include support for formatting disks (1 / 0)?
|
||||
#ifndef FATFS_INC_FORMAT_SUPPORT
|
||||
#define FATFS_INC_FORMAT_SUPPORT 1
|
||||
#endif
|
||||
|
||||
// Sector size used
|
||||
#define FAT_SECTOR_SIZE 512
|
||||
|
||||
// Printf output (directory listing / debug)
|
||||
#ifndef FAT_PRINTF
|
||||
// Don't include stdio, but there is a printf function available
|
||||
#ifdef FAT_PRINTF_NOINC_STDIO
|
||||
extern int printf(const char* ctrl1, ... );
|
||||
#define FAT_PRINTF(a) printf a
|
||||
// Include stdio to use printf
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#define FAT_PRINTF(a) printf a
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Time/Date support requires time.h
|
||||
#if FATFS_INC_TIME_DATE_SUPPORT
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#endif
|
514
vtoycli/fat_io_lib/release/fat_string.c
Normal file
514
vtoycli/fat_io_lib/release/fat_string.c
Normal file
@@ -0,0 +1,514 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 <assert.h>
|
||||
#include "fat_string.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_total_path_levels: Take a filename and path and count the sub levels
|
||||
// of folders. E.g. C:\folder\file.zip = 1 level
|
||||
// Acceptable input formats are:
|
||||
// c:\folder\file.zip
|
||||
// /dev/etc/samba.conf
|
||||
// Returns: -1 = Error, 0 or more = Ok
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_total_path_levels(char *path)
|
||||
{
|
||||
int levels = 0;
|
||||
char expectedchar;
|
||||
|
||||
if (!path)
|
||||
return -1;
|
||||
|
||||
// Acceptable formats:
|
||||
// c:\folder\file.zip
|
||||
// /dev/etc/samba.conf
|
||||
if (*path == '/')
|
||||
{
|
||||
expectedchar = '/';
|
||||
path++;
|
||||
}
|
||||
else if (path[1] == ':' || path[2] == '\\')
|
||||
{
|
||||
expectedchar = '\\';
|
||||
path += 3;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
// Count levels in path string
|
||||
while (*path)
|
||||
{
|
||||
// Fast forward through actual subdir text to next slash
|
||||
for (; *path; )
|
||||
{
|
||||
// If slash detected escape from for loop
|
||||
if (*path == expectedchar) { path++; break; }
|
||||
path++;
|
||||
}
|
||||
|
||||
// Increase number of subdirs founds
|
||||
levels++;
|
||||
}
|
||||
|
||||
// Subtract the file itself
|
||||
return levels-1;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_get_substring: Get a substring from 'path' which contains the folder
|
||||
// (or file) at the specified level.
|
||||
// E.g. C:\folder\file.zip : Level 0 = C:\folder, Level 1 = file.zip
|
||||
// Returns: -1 = Error, 0 = Ok
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_get_substring(char *path, int levelreq, char *output, int max_len)
|
||||
{
|
||||
int i;
|
||||
int pathlen=0;
|
||||
int levels=0;
|
||||
int copypnt=0;
|
||||
char expectedchar;
|
||||
|
||||
if (!path || max_len <= 0)
|
||||
return -1;
|
||||
|
||||
// Acceptable formats:
|
||||
// c:\folder\file.zip
|
||||
// /dev/etc/samba.conf
|
||||
if (*path == '/')
|
||||
{
|
||||
expectedchar = '/';
|
||||
path++;
|
||||
}
|
||||
else if (path[1] == ':' || path[2] == '\\')
|
||||
{
|
||||
expectedchar = '\\';
|
||||
path += 3;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
// Get string length of path
|
||||
pathlen = (int)strlen (path);
|
||||
|
||||
// Loop through the number of times as characters in 'path'
|
||||
for (i = 0; i<pathlen; i++)
|
||||
{
|
||||
// If a '\' is found then increase level
|
||||
if (*path == expectedchar) levels++;
|
||||
|
||||
// If correct level and the character is not a '\' or '/' then copy text to 'output'
|
||||
if ( (levels == levelreq) && (*path != expectedchar) && (copypnt < (max_len-1)))
|
||||
output[copypnt++] = *path;
|
||||
|
||||
// Increment through path string
|
||||
path++;
|
||||
}
|
||||
|
||||
// Null Terminate
|
||||
output[copypnt] = '\0';
|
||||
|
||||
// If a string was copied return 0 else return 1
|
||||
if (output[0] != '\0')
|
||||
return 0; // OK
|
||||
else
|
||||
return -1; // Error
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_split_path: Full path contains the passed in string.
|
||||
// Returned is the path string and file Name string
|
||||
// E.g. C:\folder\file.zip -> path = C:\folder filename = file.zip
|
||||
// E.g. C:\file.zip -> path = [blank] filename = file.zip
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_split_path(char *full_path, char *path, int max_path, char *filename, int max_filename)
|
||||
{
|
||||
int strindex;
|
||||
|
||||
// Count the levels to the filepath
|
||||
int levels = fatfs_total_path_levels(full_path);
|
||||
if (levels == -1)
|
||||
return -1;
|
||||
|
||||
// Get filename part of string
|
||||
if (fatfs_get_substring(full_path, levels, filename, max_filename) != 0)
|
||||
return -1;
|
||||
|
||||
// If root file
|
||||
if (levels == 0)
|
||||
path[0] = '\0';
|
||||
else
|
||||
{
|
||||
strindex = (int)strlen(full_path) - (int)strlen(filename);
|
||||
if (strindex > max_path)
|
||||
strindex = max_path;
|
||||
|
||||
memcpy(path, full_path, strindex);
|
||||
path[strindex-1] = '\0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// FileString_StrCmpNoCase: Compare two strings case with case sensitivity
|
||||
//-----------------------------------------------------------------------------
|
||||
static int FileString_StrCmpNoCase(char *s1, char *s2, int n)
|
||||
{
|
||||
int diff;
|
||||
char a,b;
|
||||
|
||||
while (n--)
|
||||
{
|
||||
a = *s1;
|
||||
b = *s2;
|
||||
|
||||
// Make lower case if uppercase
|
||||
if ((a>='A') && (a<='Z'))
|
||||
a+= 32;
|
||||
if ((b>='A') && (b<='Z'))
|
||||
b+= 32;
|
||||
|
||||
diff = a - b;
|
||||
|
||||
// If different
|
||||
if (diff)
|
||||
return diff;
|
||||
|
||||
// If run out of strings
|
||||
if ( (*s1 == 0) || (*s2 == 0) )
|
||||
break;
|
||||
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// FileString_GetExtension: Get index to extension within filename
|
||||
// Returns -1 if not found or index otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
static int FileString_GetExtension(char *str)
|
||||
{
|
||||
int dotPos = -1;
|
||||
char *strSrc = str;
|
||||
|
||||
// Find last '.' in string (if at all)
|
||||
while (*strSrc)
|
||||
{
|
||||
if (*strSrc=='.')
|
||||
dotPos = (int)(strSrc-str);
|
||||
|
||||
strSrc++;
|
||||
}
|
||||
|
||||
return dotPos;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// FileString_TrimLength: Get length of string excluding trailing spaces
|
||||
// Returns -1 if not found or index otherwise
|
||||
//-----------------------------------------------------------------------------
|
||||
static int FileString_TrimLength(char *str, int strLen)
|
||||
{
|
||||
int length = strLen;
|
||||
char *strSrc = str+strLen-1;
|
||||
|
||||
// Find last non white space
|
||||
while (strLen != 0)
|
||||
{
|
||||
if (*strSrc == ' ')
|
||||
length = (int)(strSrc - str);
|
||||
else
|
||||
break;
|
||||
|
||||
strSrc--;
|
||||
strLen--;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_compare_names: Compare two filenames (without copying or changing origonals)
|
||||
// Returns 1 if match, 0 if not
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_compare_names(char* strA, char* strB)
|
||||
{
|
||||
char *ext1 = NULL;
|
||||
char *ext2 = NULL;
|
||||
int ext1Pos, ext2Pos;
|
||||
int file1Len, file2Len;
|
||||
|
||||
// Get both files extension
|
||||
ext1Pos = FileString_GetExtension(strA);
|
||||
ext2Pos = FileString_GetExtension(strB);
|
||||
|
||||
// NOTE: Extension position can be different for matching
|
||||
// filename if trailing space are present before it!
|
||||
// Check that if one has an extension, so does the other
|
||||
if ((ext1Pos==-1) && (ext2Pos!=-1))
|
||||
return 0;
|
||||
if ((ext2Pos==-1) && (ext1Pos!=-1))
|
||||
return 0;
|
||||
|
||||
// If they both have extensions, compare them
|
||||
if (ext1Pos!=-1)
|
||||
{
|
||||
// Set pointer to start of extension
|
||||
ext1 = strA+ext1Pos+1;
|
||||
ext2 = strB+ext2Pos+1;
|
||||
|
||||
// Verify that the file extension lengths match!
|
||||
if (strlen(ext1) != strlen(ext2))
|
||||
return 0;
|
||||
|
||||
// If they dont match
|
||||
if (FileString_StrCmpNoCase(ext1, ext2, (int)strlen(ext1))!=0)
|
||||
return 0;
|
||||
|
||||
// Filelength is upto extensions
|
||||
file1Len = ext1Pos;
|
||||
file2Len = ext2Pos;
|
||||
}
|
||||
// No extensions
|
||||
else
|
||||
{
|
||||
// Filelength is actual filelength
|
||||
file1Len = (int)strlen(strA);
|
||||
file2Len = (int)strlen(strB);
|
||||
}
|
||||
|
||||
// Find length without trailing spaces (before ext)
|
||||
file1Len = FileString_TrimLength(strA, file1Len);
|
||||
file2Len = FileString_TrimLength(strB, file2Len);
|
||||
|
||||
// Check the file lengths match
|
||||
if (file1Len!=file2Len)
|
||||
return 0;
|
||||
|
||||
// Compare main part of filenames
|
||||
if (FileString_StrCmpNoCase(strA, strB, file1Len)!=0)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_string_ends_with_slash: Does the string end with a slash (\ or /)
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_string_ends_with_slash(char *path)
|
||||
{
|
||||
if (path)
|
||||
{
|
||||
while (*path)
|
||||
{
|
||||
// Last character?
|
||||
if (!(*(path+1)))
|
||||
{
|
||||
if (*path == '\\' || *path == '/')
|
||||
return 1;
|
||||
}
|
||||
|
||||
path++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_get_sfn_display_name: Get display name for SFN entry
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_get_sfn_display_name(char* out, char* in)
|
||||
{
|
||||
int len = 0;
|
||||
while (*in && len <= 11)
|
||||
{
|
||||
char a = *in++;
|
||||
|
||||
if (a == ' ')
|
||||
continue;
|
||||
// Make lower case if uppercase
|
||||
else if ((a>='A') && (a<='Z'))
|
||||
a+= 32;
|
||||
|
||||
*out++ = a;
|
||||
len++;
|
||||
}
|
||||
|
||||
*out = '\0';
|
||||
return 1;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_get_extension: Get extension of filename passed in 'filename'.
|
||||
// Returned extension is always lower case.
|
||||
// Returns: 1 if ok, 0 if not.
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_get_extension(char* filename, char* out, int maxlen)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
// Get files extension offset
|
||||
int ext_pos = FileString_GetExtension(filename);
|
||||
|
||||
if (ext_pos > 0 && out && maxlen)
|
||||
{
|
||||
filename += ext_pos + 1;
|
||||
|
||||
while (*filename && len < (maxlen-1))
|
||||
{
|
||||
char a = *filename++;
|
||||
|
||||
// Make lowercase if uppercase
|
||||
if ((a>='A') && (a<='Z'))
|
||||
a+= 32;
|
||||
|
||||
*out++ = a;
|
||||
len++;
|
||||
}
|
||||
|
||||
*out = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_create_path_string: Append path & filename to create file path string.
|
||||
// Returns: 1 if ok, 0 if not.
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_create_path_string(char* path, char *filename, char* out, int maxlen)
|
||||
{
|
||||
int len = 0;
|
||||
char last = 0;
|
||||
char seperator = '/';
|
||||
|
||||
if (path && filename && out && maxlen > 0)
|
||||
{
|
||||
while (*path && len < (maxlen-2))
|
||||
{
|
||||
last = *path++;
|
||||
if (last == '\\')
|
||||
seperator = '\\';
|
||||
*out++ = last;
|
||||
len++;
|
||||
}
|
||||
|
||||
// Add a seperator if trailing one not found
|
||||
if (last != '\\' && last != '/')
|
||||
*out++ = seperator;
|
||||
|
||||
while (*filename && len < (maxlen-1))
|
||||
{
|
||||
*out++ = *filename++;
|
||||
len++;
|
||||
}
|
||||
|
||||
*out = '\0';
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Test Bench
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef FAT_STRING_TESTBENCH
|
||||
void main(void)
|
||||
{
|
||||
char output[255];
|
||||
char output2[255];
|
||||
|
||||
assert(fatfs_total_path_levels("C:\\folder\\file.zip") == 1);
|
||||
assert(fatfs_total_path_levels("C:\\file.zip") == 0);
|
||||
assert(fatfs_total_path_levels("C:\\folder\\folder2\\file.zip") == 2);
|
||||
assert(fatfs_total_path_levels("C:\\") == -1);
|
||||
assert(fatfs_total_path_levels("") == -1);
|
||||
assert(fatfs_total_path_levels("/dev/etc/file.zip") == 2);
|
||||
assert(fatfs_total_path_levels("/dev/file.zip") == 1);
|
||||
|
||||
assert(fatfs_get_substring("C:\\folder\\file.zip", 0, output, sizeof(output)) == 0);
|
||||
assert(strcmp(output, "folder") == 0);
|
||||
|
||||
assert(fatfs_get_substring("C:\\folder\\file.zip", 1, output, sizeof(output)) == 0);
|
||||
assert(strcmp(output, "file.zip") == 0);
|
||||
|
||||
assert(fatfs_get_substring("/dev/etc/file.zip", 0, output, sizeof(output)) == 0);
|
||||
assert(strcmp(output, "dev") == 0);
|
||||
|
||||
assert(fatfs_get_substring("/dev/etc/file.zip", 1, output, sizeof(output)) == 0);
|
||||
assert(strcmp(output, "etc") == 0);
|
||||
|
||||
assert(fatfs_get_substring("/dev/etc/file.zip", 2, output, sizeof(output)) == 0);
|
||||
assert(strcmp(output, "file.zip") == 0);
|
||||
|
||||
assert(fatfs_split_path("C:\\folder\\file.zip", output, sizeof(output), output2, sizeof(output2)) == 0);
|
||||
assert(strcmp(output, "C:\\folder") == 0);
|
||||
assert(strcmp(output2, "file.zip") == 0);
|
||||
|
||||
assert(fatfs_split_path("C:\\file.zip", output, sizeof(output), output2, sizeof(output2)) == 0);
|
||||
assert(output[0] == 0);
|
||||
assert(strcmp(output2, "file.zip") == 0);
|
||||
|
||||
assert(fatfs_split_path("/dev/etc/file.zip", output, sizeof(output), output2, sizeof(output2)) == 0);
|
||||
assert(strcmp(output, "/dev/etc") == 0);
|
||||
assert(strcmp(output2, "file.zip") == 0);
|
||||
|
||||
assert(FileString_GetExtension("C:\\file.zip") == strlen("C:\\file"));
|
||||
assert(FileString_GetExtension("C:\\file.zip.ext") == strlen("C:\\file.zip"));
|
||||
assert(FileString_GetExtension("C:\\file.zip.") == strlen("C:\\file.zip"));
|
||||
|
||||
assert(FileString_TrimLength("C:\\file.zip", strlen("C:\\file.zip")) == strlen("C:\\file.zip"));
|
||||
assert(FileString_TrimLength("C:\\file.zip ", strlen("C:\\file.zip ")) == strlen("C:\\file.zip"));
|
||||
assert(FileString_TrimLength(" ", strlen(" ")) == 0);
|
||||
|
||||
assert(fatfs_compare_names("C:\\file.ext", "C:\\file.ext") == 1);
|
||||
assert(fatfs_compare_names("C:\\file2.ext", "C:\\file.ext") == 0);
|
||||
assert(fatfs_compare_names("C:\\file .ext", "C:\\file.ext") == 1);
|
||||
assert(fatfs_compare_names("C:\\file .ext", "C:\\file2.ext") == 0);
|
||||
|
||||
assert(fatfs_string_ends_with_slash("C:\\folder") == 0);
|
||||
assert(fatfs_string_ends_with_slash("C:\\folder\\") == 1);
|
||||
assert(fatfs_string_ends_with_slash("/path") == 0);
|
||||
assert(fatfs_string_ends_with_slash("/path/a") == 0);
|
||||
assert(fatfs_string_ends_with_slash("/path/") == 1);
|
||||
|
||||
assert(fatfs_get_extension("/mypath/file.wav", output, 4) == 1);
|
||||
assert(strcmp(output, "wav") == 0);
|
||||
assert(fatfs_get_extension("/mypath/file.WAV", output, 4) == 1);
|
||||
assert(strcmp(output, "wav") == 0);
|
||||
assert(fatfs_get_extension("/mypath/file.zip", output, 4) == 1);
|
||||
assert(strcmp(output, "ext") != 0);
|
||||
|
||||
assert(fatfs_create_path_string("/mydir1", "myfile.txt", output, sizeof(output)) == 1);
|
||||
assert(strcmp(output, "/mydir1/myfile.txt") == 0);
|
||||
assert(fatfs_create_path_string("/mydir2/", "myfile2.txt", output, sizeof(output)) == 1);
|
||||
assert(strcmp(output, "/mydir2/myfile2.txt") == 0);
|
||||
assert(fatfs_create_path_string("C:\\mydir3", "myfile3.txt", output, sizeof(output)) == 1);
|
||||
assert(strcmp(output, "C:\\mydir3\\myfile3.txt") == 0);
|
||||
}
|
||||
#endif
|
20
vtoycli/fat_io_lib/release/fat_string.h
Normal file
20
vtoycli/fat_io_lib/release/fat_string.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef __FILESTRING_H__
|
||||
#define __FILESTRING_H__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Prototypes
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_total_path_levels(char *path);
|
||||
int fatfs_get_substring(char *Path, int levelreq, char *output, int max_len);
|
||||
int fatfs_split_path(char *FullPath, char *Path, int max_path, char *FileName, int max_filename);
|
||||
int fatfs_compare_names(char* strA, char* strB);
|
||||
int fatfs_string_ends_with_slash(char *path);
|
||||
int fatfs_get_sfn_display_name(char* out, char* in);
|
||||
int fatfs_get_extension(char* filename, char* out, int maxlen);
|
||||
int fatfs_create_path_string(char* path, char *filename, char* out, int maxlen);
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#endif
|
478
vtoycli/fat_io_lib/release/fat_table.c
Normal file
478
vtoycli/fat_io_lib/release/fat_table.c
Normal file
@@ -0,0 +1,478 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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"
|
||||
|
||||
#ifndef FAT_BUFFERS
|
||||
#define FAT_BUFFERS 1
|
||||
#endif
|
||||
|
||||
#ifndef FAT_BUFFER_SECTORS
|
||||
#define FAT_BUFFER_SECTORS 1
|
||||
#endif
|
||||
|
||||
#if FAT_BUFFERS < 1 || FAT_BUFFER_SECTORS < 1
|
||||
#error "FAT_BUFFERS & FAT_BUFFER_SECTORS must be at least 1"
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FAT Sector Buffer
|
||||
//-----------------------------------------------------------------------------
|
||||
#define FAT32_GET_32BIT_WORD(pbuf, location) ( GET_32BIT_WORD(pbuf->ptr, location) )
|
||||
#define FAT32_SET_32BIT_WORD(pbuf, location, value) { SET_32BIT_WORD(pbuf->ptr, location, value); pbuf->dirty = 1; }
|
||||
#define FAT16_GET_16BIT_WORD(pbuf, location) ( GET_16BIT_WORD(pbuf->ptr, location) )
|
||||
#define FAT16_SET_16BIT_WORD(pbuf, location, value) { SET_16BIT_WORD(pbuf->ptr, location, value); pbuf->dirty = 1; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_fat_init:
|
||||
//-----------------------------------------------------------------------------
|
||||
void fatfs_fat_init(struct fatfs *fs)
|
||||
{
|
||||
int i;
|
||||
|
||||
// FAT buffer chain head
|
||||
fs->fat_buffer_head = NULL;
|
||||
|
||||
for (i=0;i<FAT_BUFFERS;i++)
|
||||
{
|
||||
// Initialise buffers to invalid
|
||||
fs->fat_buffers[i].address = FAT32_INVALID_CLUSTER;
|
||||
fs->fat_buffers[i].dirty = 0;
|
||||
memset(fs->fat_buffers[i].sector, 0x00, sizeof(fs->fat_buffers[i].sector));
|
||||
fs->fat_buffers[i].ptr = NULL;
|
||||
|
||||
// Add to head of queue
|
||||
fs->fat_buffers[i].next = fs->fat_buffer_head;
|
||||
fs->fat_buffer_head = &fs->fat_buffers[i];
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_fat_writeback: Writeback 'dirty' FAT sectors to disk
|
||||
//-----------------------------------------------------------------------------
|
||||
static int fatfs_fat_writeback(struct fatfs *fs, struct fat_buffer *pcur)
|
||||
{
|
||||
if (pcur)
|
||||
{
|
||||
// Writeback sector if changed
|
||||
if (pcur->dirty)
|
||||
{
|
||||
if (fs->disk_io.write_media)
|
||||
{
|
||||
uint32 sectors = FAT_BUFFER_SECTORS;
|
||||
uint32 offset = pcur->address - fs->fat_begin_lba;
|
||||
|
||||
// Limit to sectors used for the FAT
|
||||
if ((offset + FAT_BUFFER_SECTORS) <= fs->fat_sectors)
|
||||
sectors = FAT_BUFFER_SECTORS;
|
||||
else
|
||||
sectors = fs->fat_sectors - offset;
|
||||
|
||||
if (!fs->disk_io.write_media(pcur->address, pcur->sector, sectors))
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcur->dirty = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_fat_read_sector: Read a FAT sector
|
||||
//-----------------------------------------------------------------------------
|
||||
static struct fat_buffer *fatfs_fat_read_sector(struct fatfs *fs, uint32 sector)
|
||||
{
|
||||
struct fat_buffer *last = NULL;
|
||||
struct fat_buffer *pcur = fs->fat_buffer_head;
|
||||
|
||||
// Itterate through sector buffer list
|
||||
while (pcur)
|
||||
{
|
||||
// Sector within this buffer?
|
||||
if ((sector >= pcur->address) && (sector < (pcur->address + FAT_BUFFER_SECTORS)))
|
||||
break;
|
||||
|
||||
// End of list?
|
||||
if (pcur->next == NULL)
|
||||
{
|
||||
// Remove buffer from list
|
||||
if (last)
|
||||
last->next = NULL;
|
||||
// We the first and last buffer in the chain?
|
||||
else
|
||||
fs->fat_buffer_head = NULL;
|
||||
}
|
||||
|
||||
last = pcur;
|
||||
pcur = pcur->next;
|
||||
}
|
||||
|
||||
// We found the sector already in FAT buffer chain
|
||||
if (pcur)
|
||||
{
|
||||
pcur->ptr = (uint8 *)(pcur->sector + ((sector - pcur->address) * FAT_SECTOR_SIZE));
|
||||
return pcur;
|
||||
}
|
||||
|
||||
// Else, we removed the last item from the list
|
||||
pcur = last;
|
||||
|
||||
// Add to start of sector buffer list (now newest sector)
|
||||
pcur->next = fs->fat_buffer_head;
|
||||
fs->fat_buffer_head = pcur;
|
||||
|
||||
// Writeback sector if changed
|
||||
if (pcur->dirty)
|
||||
if (!fatfs_fat_writeback(fs, pcur))
|
||||
return 0;
|
||||
|
||||
// Address is now new sector
|
||||
pcur->address = sector;
|
||||
|
||||
// Read next sector
|
||||
if (!fs->disk_io.read_media(pcur->address, pcur->sector, FAT_BUFFER_SECTORS))
|
||||
{
|
||||
// Read failed, invalidate buffer address
|
||||
pcur->address = FAT32_INVALID_CLUSTER;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pcur->ptr = pcur->sector;
|
||||
return pcur;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_fat_purge: Purge 'dirty' FAT sectors to disk
|
||||
//-----------------------------------------------------------------------------
|
||||
int fatfs_fat_purge(struct fatfs *fs)
|
||||
{
|
||||
struct fat_buffer *pcur = fs->fat_buffer_head;
|
||||
|
||||
// Itterate through sector buffer list
|
||||
while (pcur)
|
||||
{
|
||||
// Writeback sector if changed
|
||||
if (pcur->dirty)
|
||||
if (!fatfs_fat_writeback(fs, pcur))
|
||||
return 0;
|
||||
|
||||
pcur = pcur->next;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// General FAT Table Operations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_find_next_cluster: Return cluster number of next cluster in chain by
|
||||
// reading FAT table and traversing it. Return 0xffffffff for end of chain.
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32 fatfs_find_next_cluster(struct fatfs *fs, uint32 current_cluster)
|
||||
{
|
||||
uint32 fat_sector_offset, position;
|
||||
uint32 nextcluster;
|
||||
struct fat_buffer *pbuf;
|
||||
|
||||
// Why is '..' labelled with cluster 0 when it should be 2 ??
|
||||
if (current_cluster == 0)
|
||||
current_cluster = 2;
|
||||
|
||||
// Find which sector of FAT table to read
|
||||
if (fs->fat_type == FAT_TYPE_16)
|
||||
fat_sector_offset = current_cluster / 256;
|
||||
else
|
||||
fat_sector_offset = current_cluster / 128;
|
||||
|
||||
// Read FAT sector into buffer
|
||||
pbuf = fatfs_fat_read_sector(fs, fs->fat_begin_lba+fat_sector_offset);
|
||||
if (!pbuf)
|
||||
return (FAT32_LAST_CLUSTER);
|
||||
|
||||
if (fs->fat_type == FAT_TYPE_16)
|
||||
{
|
||||
// Find 32 bit entry of current sector relating to cluster number
|
||||
position = (current_cluster - (fat_sector_offset * 256)) * 2;
|
||||
|
||||
// Read Next Clusters value from Sector Buffer
|
||||
nextcluster = FAT16_GET_16BIT_WORD(pbuf, (uint16)position);
|
||||
|
||||
// If end of chain found
|
||||
if (nextcluster >= 0xFFF8 && nextcluster <= 0xFFFF)
|
||||
return (FAT32_LAST_CLUSTER);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find 32 bit entry of current sector relating to cluster number
|
||||
position = (current_cluster - (fat_sector_offset * 128)) * 4;
|
||||
|
||||
// Read Next Clusters value from Sector Buffer
|
||||
nextcluster = FAT32_GET_32BIT_WORD(pbuf, (uint16)position);
|
||||
|
||||
// Mask out MS 4 bits (its 28bit addressing)
|
||||
nextcluster = nextcluster & 0x0FFFFFFF;
|
||||
|
||||
// If end of chain found
|
||||
if (nextcluster >= 0x0FFFFFF8 && nextcluster <= 0x0FFFFFFF)
|
||||
return (FAT32_LAST_CLUSTER);
|
||||
}
|
||||
|
||||
// Else return next cluster
|
||||
return (nextcluster);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_set_fs_info_next_free_cluster: Write the next free cluster to the FSINFO table
|
||||
//-----------------------------------------------------------------------------
|
||||
void fatfs_set_fs_info_next_free_cluster(struct fatfs *fs, uint32 newValue)
|
||||
{
|
||||
if (fs->fat_type == FAT_TYPE_16)
|
||||
;
|
||||
else
|
||||
{
|
||||
// Load sector to change it
|
||||
struct fat_buffer *pbuf = fatfs_fat_read_sector(fs, fs->lba_begin+fs->fs_info_sector);
|
||||
if (!pbuf)
|
||||
return ;
|
||||
|
||||
// Change
|
||||
FAT32_SET_32BIT_WORD(pbuf, 492, newValue);
|
||||
fs->next_free_cluster = newValue;
|
||||
|
||||
// Write back FSINFO sector to disk
|
||||
if (fs->disk_io.write_media)
|
||||
fs->disk_io.write_media(pbuf->address, pbuf->sector, 1);
|
||||
|
||||
// Invalidate cache entry
|
||||
pbuf->address = FAT32_INVALID_CLUSTER;
|
||||
pbuf->dirty = 0;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_find_blank_cluster: Find a free cluster entry by reading the FAT
|
||||
//-----------------------------------------------------------------------------
|
||||
#if FATFS_INC_WRITE_SUPPORT
|
||||
int fatfs_find_blank_cluster(struct fatfs *fs, uint32 start_cluster, uint32 *free_cluster)
|
||||
{
|
||||
uint32 fat_sector_offset, position;
|
||||
uint32 nextcluster;
|
||||
uint32 current_cluster = start_cluster;
|
||||
struct fat_buffer *pbuf;
|
||||
|
||||
do
|
||||
{
|
||||
// Find which sector of FAT table to read
|
||||
if (fs->fat_type == FAT_TYPE_16)
|
||||
fat_sector_offset = current_cluster / 256;
|
||||
else
|
||||
fat_sector_offset = current_cluster / 128;
|
||||
|
||||
if ( fat_sector_offset < fs->fat_sectors)
|
||||
{
|
||||
// Read FAT sector into buffer
|
||||
pbuf = fatfs_fat_read_sector(fs, fs->fat_begin_lba+fat_sector_offset);
|
||||
if (!pbuf)
|
||||
return 0;
|
||||
|
||||
if (fs->fat_type == FAT_TYPE_16)
|
||||
{
|
||||
// Find 32 bit entry of current sector relating to cluster number
|
||||
position = (current_cluster - (fat_sector_offset * 256)) * 2;
|
||||
|
||||
// Read Next Clusters value from Sector Buffer
|
||||
nextcluster = FAT16_GET_16BIT_WORD(pbuf, (uint16)position);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find 32 bit entry of current sector relating to cluster number
|
||||
position = (current_cluster - (fat_sector_offset * 128)) * 4;
|
||||
|
||||
// Read Next Clusters value from Sector Buffer
|
||||
nextcluster = FAT32_GET_32BIT_WORD(pbuf, (uint16)position);
|
||||
|
||||
// Mask out MS 4 bits (its 28bit addressing)
|
||||
nextcluster = nextcluster & 0x0FFFFFFF;
|
||||
}
|
||||
|
||||
if (nextcluster !=0 )
|
||||
current_cluster++;
|
||||
}
|
||||
else
|
||||
// Otherwise, run out of FAT sectors to check...
|
||||
return 0;
|
||||
}
|
||||
while (nextcluster != 0x0);
|
||||
|
||||
// Found blank entry
|
||||
*free_cluster = current_cluster;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_fat_set_cluster: Set a cluster link in the chain. NOTE: Immediate
|
||||
// write (slow).
|
||||
//-----------------------------------------------------------------------------
|
||||
#if FATFS_INC_WRITE_SUPPORT
|
||||
int fatfs_fat_set_cluster(struct fatfs *fs, uint32 cluster, uint32 next_cluster)
|
||||
{
|
||||
struct fat_buffer *pbuf;
|
||||
uint32 fat_sector_offset, position;
|
||||
|
||||
// Find which sector of FAT table to read
|
||||
if (fs->fat_type == FAT_TYPE_16)
|
||||
fat_sector_offset = cluster / 256;
|
||||
else
|
||||
fat_sector_offset = cluster / 128;
|
||||
|
||||
// Read FAT sector into buffer
|
||||
pbuf = fatfs_fat_read_sector(fs, fs->fat_begin_lba+fat_sector_offset);
|
||||
if (!pbuf)
|
||||
return 0;
|
||||
|
||||
if (fs->fat_type == FAT_TYPE_16)
|
||||
{
|
||||
// Find 16 bit entry of current sector relating to cluster number
|
||||
position = (cluster - (fat_sector_offset * 256)) * 2;
|
||||
|
||||
// Write Next Clusters value to Sector Buffer
|
||||
FAT16_SET_16BIT_WORD(pbuf, (uint16)position, ((uint16)next_cluster));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find 32 bit entry of current sector relating to cluster number
|
||||
position = (cluster - (fat_sector_offset * 128)) * 4;
|
||||
|
||||
// Write Next Clusters value to Sector Buffer
|
||||
FAT32_SET_32BIT_WORD(pbuf, (uint16)position, next_cluster);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_free_cluster_chain: Follow a chain marking each element as free
|
||||
//-----------------------------------------------------------------------------
|
||||
#if FATFS_INC_WRITE_SUPPORT
|
||||
int fatfs_free_cluster_chain(struct fatfs *fs, uint32 start_cluster)
|
||||
{
|
||||
uint32 last_cluster;
|
||||
uint32 next_cluster = start_cluster;
|
||||
|
||||
// Loop until end of chain
|
||||
while ( (next_cluster != FAT32_LAST_CLUSTER) && (next_cluster != 0x00000000) )
|
||||
{
|
||||
last_cluster = next_cluster;
|
||||
|
||||
// Find next link
|
||||
next_cluster = fatfs_find_next_cluster(fs, next_cluster);
|
||||
|
||||
// Clear last link
|
||||
fatfs_fat_set_cluster(fs, last_cluster, 0x00000000);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_fat_add_cluster_to_chain: Follow a chain marking and then add a new entry
|
||||
// to the current tail.
|
||||
//-----------------------------------------------------------------------------
|
||||
#if FATFS_INC_WRITE_SUPPORT
|
||||
int fatfs_fat_add_cluster_to_chain(struct fatfs *fs, uint32 start_cluster, uint32 newEntry)
|
||||
{
|
||||
uint32 last_cluster = FAT32_LAST_CLUSTER;
|
||||
uint32 next_cluster = start_cluster;
|
||||
|
||||
if (start_cluster == FAT32_LAST_CLUSTER)
|
||||
return 0;
|
||||
|
||||
// Loop until end of chain
|
||||
while ( next_cluster != FAT32_LAST_CLUSTER )
|
||||
{
|
||||
last_cluster = next_cluster;
|
||||
|
||||
// Find next link
|
||||
next_cluster = fatfs_find_next_cluster(fs, next_cluster);
|
||||
if (!next_cluster)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add link in for new cluster
|
||||
fatfs_fat_set_cluster(fs, last_cluster, newEntry);
|
||||
|
||||
// Mark new cluster as end of chain
|
||||
fatfs_fat_set_cluster(fs, newEntry, FAT32_LAST_CLUSTER);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// fatfs_count_free_clusters:
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32 fatfs_count_free_clusters(struct fatfs *fs)
|
||||
{
|
||||
uint32 i,j;
|
||||
uint32 count = 0;
|
||||
struct fat_buffer *pbuf;
|
||||
|
||||
for (i = 0; i < fs->fat_sectors; i++)
|
||||
{
|
||||
// Read FAT sector into buffer
|
||||
pbuf = fatfs_fat_read_sector(fs, fs->fat_begin_lba + i);
|
||||
if (!pbuf)
|
||||
break;
|
||||
|
||||
for (j = 0; j < FAT_SECTOR_SIZE; )
|
||||
{
|
||||
if (fs->fat_type == FAT_TYPE_16)
|
||||
{
|
||||
if (FAT16_GET_16BIT_WORD(pbuf, (uint16)j) == 0)
|
||||
count++;
|
||||
|
||||
j += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FAT32_GET_32BIT_WORD(pbuf, (uint16)j) == 0)
|
||||
count++;
|
||||
|
||||
j += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
20
vtoycli/fat_io_lib/release/fat_table.h
Normal file
20
vtoycli/fat_io_lib/release/fat_table.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef __FAT_TABLE_H__
|
||||
#define __FAT_TABLE_H__
|
||||
|
||||
#include "fat_opts.h"
|
||||
#include "fat_misc.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Prototypes
|
||||
//-----------------------------------------------------------------------------
|
||||
void fatfs_fat_init(struct fatfs *fs);
|
||||
int fatfs_fat_purge(struct fatfs *fs);
|
||||
uint32 fatfs_find_next_cluster(struct fatfs *fs, uint32 current_cluster);
|
||||
void fatfs_set_fs_info_next_free_cluster(struct fatfs *fs, uint32 newValue);
|
||||
int fatfs_find_blank_cluster(struct fatfs *fs, uint32 start_cluster, uint32 *free_cluster);
|
||||
int fatfs_fat_set_cluster(struct fatfs *fs, uint32 cluster, uint32 next_cluster);
|
||||
int fatfs_fat_add_cluster_to_chain(struct fatfs *fs, uint32 start_cluster, uint32 newEntry);
|
||||
int fatfs_free_cluster_chain(struct fatfs *fs, uint32 start_cluster);
|
||||
uint32 fatfs_count_free_clusters(struct fatfs *fs);
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user