Last active
June 22, 2020 20:01
-
-
Save GXTX/3bd63bc3d67e50aab27bb6d0c71e3ba3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
backup.c | |
An application which will backup the manufacturing config sectors & | |
eeprom while optionally clearing the config sector. | |
---------------- | |
Copyright (C) 2020 wutno (https://github.com/GXTX) | |
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., | |
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
*/ | |
#include <hal/debug.h> | |
#include <hal/video.h> | |
#include <nxdk/mount.h> | |
#include <windows.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
BOOL read_config(unsigned char *config_buffer) | |
{ | |
HANDLE file_handle; | |
IO_STATUS_BLOCK status_block; | |
OBJECT_ATTRIBUTES obj_attributes; | |
ANSI_STRING file_name; | |
NTSTATUS return_status; | |
LARGE_INTEGER read_offset = { 0x00, 0x00 }; | |
unsigned int sector_size = 0x80000; | |
RtlInitAnsiString(&file_name, "\\Device\\Harddisk0\\Partition0"); | |
InitializeObjectAttributes(&obj_attributes, &file_name, OBJ_CASE_INSENSITIVE, NULL, NULL); | |
return_status = NtOpenFile(&file_handle, GENERIC_ALL, &obj_attributes, &status_block, FILE_SHARE_READ, 0); | |
if (!NT_SUCCESS(return_status)) { | |
debugPrint("Failed opening drive. Status: 0x%08X\n", return_status); | |
NtClose(file_handle); | |
return FALSE; | |
} | |
return_status = NtReadFile(file_handle, NULL, NULL, NULL, &status_block, config_buffer, sector_size, &read_offset); | |
if (!NT_SUCCESS(return_status)) { | |
debugPrint("Failed reading from the drive. Status: 0x%08X\n", return_status); | |
NtClose(file_handle); | |
return FALSE; | |
} | |
NtClose(file_handle); | |
return TRUE; | |
} | |
BOOL clear_config(unsigned char *current_config) | |
{ | |
HANDLE file_handle; | |
IO_STATUS_BLOCK status_block; | |
OBJECT_ATTRIBUTES obj_attributes; | |
ANSI_STRING file_name; | |
NTSTATUS return_status; | |
RtlInitAnsiString(&file_name, "\\Device\\Harddisk0\\Partition0"); | |
InitializeObjectAttributes(&obj_attributes, &file_name, OBJ_CASE_INSENSITIVE, NULL, NULL); | |
return_status = NtOpenFile(&file_handle, GENERIC_ALL, &obj_attributes, &status_block, FILE_SHARE_WRITE, 0); | |
if (!NT_SUCCESS(return_status)) { | |
debugPrint("Failed opening drive. Status: 0x%08X\n", return_status); | |
NtClose(file_handle); | |
return FALSE; | |
} | |
debugPrint("Writing to drive...\n"); | |
LARGE_INTEGER read_offset = { 0x00, 0x00 }; | |
memset((current_config + 0x600 + 0x10), 0x00, (0x80000 - 0x600 + 0x10)); | |
return_status = NtWriteFile(file_handle, NULL, NULL, NULL, &status_block, current_config, 0x80000, &read_offset); | |
if (!NT_SUCCESS(return_status)) { | |
debugPrint("Failed writing to the drive. Status: 0x%08X\n", return_status); | |
NtClose(file_handle); | |
return FALSE; | |
} else { | |
debugPrint("Sucessfully cleared config sector.\n"); | |
} | |
NtClose(file_handle); | |
return TRUE; | |
} | |
BOOL read_eeprom(unsigned char *eeprom_buffer) | |
{ | |
ULONG bytes_read; | |
ULONG eeprom_type; | |
ExQueryNonVolatileSetting(0xFFFF, &eeprom_type, eeprom_buffer, 256, &bytes_read); | |
if (bytes_read != 256) { | |
debugPrint("Failed reading the eeprom. Expected 256, got %02d.\n", bytes_read); | |
return FALSE; | |
} | |
return TRUE; | |
} | |
BOOL write_file(const char *name, unsigned char *buffer, size_t buffer_size){ | |
FILE *file; | |
file = fopen(name, "w"); | |
if (file == NULL) { | |
debugPrint("Failed opening file to write.\n"); | |
return FALSE; | |
} | |
if (fwrite(buffer, 1, buffer_size, file) != buffer_size) { | |
debugPrint("Failed writing the buffer to disk.\n"); | |
fclose(file); | |
return FALSE; | |
} | |
fclose(file); | |
return TRUE; | |
} | |
int main(void) | |
{ | |
XVideoSetMode(640, 480, 32, REFRESH_DEFAULT); | |
if (!nxMountDrive('E', "\\Device\\Harddisk0\\Partition1\\")) { | |
debugPrint("Failed to mount E: drive!\n"); | |
goto go_to_end; | |
} | |
unsigned char *config_buffer = malloc(0x80000); | |
unsigned char* eeprom_buffer = malloc(0x100); | |
const char *config_name = "E:\\config.bin"; | |
const char *eeprom_name = "E:\\eeprom.bin"; | |
debugPrint("Reading config sector...\n"); | |
if (!read_config(config_buffer)) { | |
goto go_to_end; | |
} | |
debugPrint("Reading EEPROM...\n"); | |
if (!read_eeprom(eeprom_buffer)) { | |
goto go_to_end; | |
} | |
if (!write_file(config_name, config_buffer, 0x80000) || !write_file(eeprom_name, eeprom_buffer, 0x100)) { | |
goto go_to_end; | |
} | |
debugPrint("Sucessfully wrote backup files.\n"); | |
//debugPrint("Clearing the config sector.\n"); | |
// Remove me if you don't want to clear the config sector. | |
//clear_config(config_buffer); | |
go_to_end: | |
Sleep(10000); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment