mirror of
https://github.com/GaryOderNichts/recovery_menu.git
synced 2025-06-19 03:05:32 -04:00

* SubmitSystemData.c: Initial "Submit System Data" function. This will allow users to submit anonymized system information, including a masked-off serial number and MLC manufacturer, so we can try to figure out which serial numbers correspond to which MLC manufacturer, among other things. This screen has been implemented using a separate .c file instead of adding it somewhere in menu.c. I'll split other screens into separate .c files later. imports.ld: Added IOSC_GenerateHash() from Gary. TODO: gethostbyname() for DNS lookup. * SubmitSystemData.c: Use an array of strings for the description. Code size difference: text data bss dec hex filename 27208 0 9696 36904 9028 ios_mcp.elf [before] 26992 0 9696 36688 8f50 ios_mcp.elf [after] -216 0 0 -216 -d8 Difference * SubmitSystemData.c: Add some more stuff to the hash. * SubmitSystemData.c: Submit the system data to wiiu.gerbilsoft.com. Using http instead of https due to the complexity of using https within the recovery_menu environment, and Wii U doesn't support TLS 1.2 natively. TODO: - Implement gethostbyname(). - Check the HTTP response code. * StartWupserver.c: Split option_StartWupserver() out of menu.c. * menu.c: Split netconf init from StartWupserver and SubmitSystemData into initNetconf(). Takes an 'index' (Y position) parameter and returns a new Y position, or 0 if an error occurred. Removed the "+ 4" from the Wupserver version. Added "+ 4" to the other messages in Wupserver. * SystemInformation.c: Split out option_SystemInformation() into a separate file. * DebugSystemRegion.c: Split out option_DebugSystemRegion() into a separate file. * Makefile: Add -Werror=implicit-function-declaration. An implicit function declaration almost always means a header is missing, and will likely result in a link error later on. * menu.c: Add a GitHub repository link to the bottom of the main menu. Well, it's a link in that it's blue and underlined, but you can't exactly click it here... * SubmitSystemData.c: Set ddr3Size and ddr3Speed. * SubmitSystemData.c: Look up the domain name instead of using a hard-coded IP address. netdb.c: gethostbyname() implementation by @GaryOderNichts. * SubmitSystemData.c: Parse the HTTP response to show actual successes or failures. Only the response code is parsed and the response message is shown. TODO: Show the actual message from the server. * gfx.h: Add a new attribute GfxPrintFlag_Underline. This prints an underscore character on top of every character that's printed, resulting in an underline effect. Removed the manual underlining code elsewhere. Code size difference: text data bss dec hex filename 29068 0 10400 39468 9a2c ios_mcp.elf [before] 28996 0 10400 39396 99e4 ios_mcp.elf [after] -72 0 0 -72 -48 Difference * SystemInformation.c: Display the BSP revision. This uses bspGetHardwareVersion(). [imports.ld value provided by Gary] The BSP version is roughly equivalent to the Console Type value found on Wii and GameCube, though libogc doesn't set it properly... Most retail systems will be 0x25100028. (A5X Cafe) Rearranged System Information to use three columns for the main data. MLC information is still shown below the main data. * SubmitSystemData: Add the BSP revision to the submitted data. * Use gfx_print() instead of gfx_printf() when formatting isn't needed. * PairDRC.c: Split "Pair DRC" into a separate file. * SubmitSystemData.c: Get the HTTP message body and print it on screen. Only the HTTP response code and message body will be displayed in either green or red. The message printed afterwards will be white. NOTE: We need to use a fairly large buffer for the HTTP response because Cloudflare adds a ton of headers. For example, an HTTP/1.1 200 OK response with the following message: "System ID is #1. This system was already submitted." has a 648-byte HTTP response, mostly due to Cloudflare's "Report-To" header. To be on the safe side, we'll allow use of the entire buffer allocated for OTP, SEEPROM, and the POST data struct, since none of those are needed after sending the HTTP request header. (2,048 bytes) * gfx_print(): Add support for newlines. ('\n') If a newline is encountered in a string, the x position will be reset to the original x position specified by the caller, and the y position will be advanced by one line. The final y position is returned by the function. This allows us to consolidate many individual calls to gfx_print() and/or gfx_printf() into a single call. Code size differences: text data bss dec hex filename 29332 0 10400 39732 9b34 ios_mcp.elf [before] 29364 0 10400 39764 9b54 ios_mcp.elf [add '\n' to gfx_print] 29220 0 10400 39620 9ac4 ios_mcp.elf [update SubmitSystemData.c] -112 0 0 -112 -70 Difference Simply updating SubmitSystemData.c to take advantage of the newline support wiped out the code size increase from adding it. NOTE: The newline support currently only supports adding a single line, not CHAR_SIZE_DRC_Y + 4. +4 is commonly used for menus, which can't take advantage of the newline support anyway. * SystemInformation.c: Make use of newlines for part of the MLC information display. New flag GfxPrintFlag_NewlinePlus4 that adds CHAR_SIZE_DRC_Y + 4 for newlines instead of just CHAR_SIZE_DRC_Y. Code size difference: text data bss dec hex filename 29220 0 10400 39620 9ac4 ios_mcp.elf [before] 29148 0 10400 39548 9a7c ios_mcp.elf [after] -72 0 0 -72 -48 Difference * DebugSystemRegion.c: Some minor optimizations. Code size difference: text data bss dec hex filename 29148 0 10400 39548 9a7c ios_mcp.elf [before] 29124 0 10400 39524 9a64 ios_mcp.elf [after] -24 0 0 -24 -18 Difference * SubmitSystemData.c: Make dataBuffer uint8_t*; use it instead of otp for the recv buffer. This reduces confusion, even though otp and dataBuffer are technically the same buffer. Fix a one-byte overflow when ensuring dataBuffer is NULL-terminated. * initNetconf(): Use a pointer for index and return an actual error code. * Makefile: Add -Werror=int-conversion. * SubmitSystemData.c: Submit ddr3Vendor and MLC CID. Using empty space in the POST data structure instead of shuffling it around to preserve compatibility (for now). * SystemInformation.c: Display BSP revision name and DDR3 information. * SystemInformation.c: Fix text alignment of Column 2's data. * SubmitSystemData.c: Verify the send() return values. * SubmitSystemData.c: Use RSA+AES encryption when submitting data. Since we can't use https, use the next best thing. NOTE: mini-gmp puts us very close to the 40K .text limit: text data bss dec hex filename 39612 0 10400 50012 c35c ios_mcp.elf TODO: Investigate using Thumb mode later. * imports.h: Clarify that these IOSC_GenerateHash() flags are for SHA-256. Also add SHA-1 flags. * SubmitSystemData.c: Send MS, CA, NG, and NG key IDs, and device certificate. Device certificate is recommended in order to really verify the system information is authentic. It will be checked against MS, CA, NG, and NG key IDs. Rearrange the POST data struct to work better. Remove MLC name1, since the device name is part of the CID. NOTE: This requires a server-side change. * SubmitSystemData.c: Make the submitted info screen match WiiUIdent. * SubmitSystemData.c: Handle newlines in the server's response message.
258 lines
6.9 KiB
C
258 lines
6.9 KiB
C
#include "gfx.h"
|
|
#include "imports.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
static uint32_t* const TV_FRAMEBUFFER = (uint32_t*)(0x14000000 + 0x3500000);
|
|
#define TV_HEIGHT 720
|
|
#define TV_STRIDE 1280
|
|
|
|
static uint32_t* const DRC_FRAMEBUFFER = (uint32_t*)(0x14000000 + 0x38c0000);
|
|
#define DRC_HEIGHT 480
|
|
#define DRC_STRIDE 896
|
|
|
|
#define CHAR_SIZE_TV_X 12
|
|
#define CHAR_SIZE_TV_Y 24
|
|
|
|
// Default font color is white.
|
|
static uint32_t font_color = 0xFFFFFFFF;
|
|
|
|
// Terminus fonts (8x16 for DRC, 12x24 for TV)
|
|
// NOTE: Allocated using IOS_HeapAlloc().
|
|
#include "font_bin.h"
|
|
#include "minilzo/minilzo.h"
|
|
static terminus_font* font = NULL;
|
|
|
|
int gfx_init_font(void)
|
|
{
|
|
if (font)
|
|
return 0;
|
|
|
|
font = IOS_HeapAlloc(LOCAL_PROCESS_HEAP_ID, sizeof(*font));
|
|
if (!font) {
|
|
printf("Memory allocation for the font buffer failed!\n");
|
|
return -1;
|
|
}
|
|
|
|
lzo_uint data_len = sizeof(*font);
|
|
int res = lzo1x_decompress_safe(terminus_lzo1x, sizeof(terminus_lzo1x),
|
|
(lzo_bytep)font, &data_len, NULL);
|
|
if (res != LZO_E_OK || data_len != sizeof(*font)) {
|
|
// LZO decompression failed.
|
|
printf("lzo1x_decompress() failed: res == %d, data_len == %lu\n", res, data_len);
|
|
IOS_HeapFree(LOCAL_PROCESS_HEAP_ID, font);
|
|
font = NULL;
|
|
return -2;
|
|
}
|
|
|
|
// LZO decompression succeeded.
|
|
return 0;
|
|
}
|
|
|
|
void gfx_clear(uint32_t col)
|
|
{
|
|
#ifdef DC_INIT
|
|
// both DC configurations use XRGB instead of RGBX
|
|
col >>= 8;
|
|
#endif
|
|
|
|
for (uint32_t i = 0; i < TV_STRIDE * TV_HEIGHT; i++) {
|
|
TV_FRAMEBUFFER[i] = col;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < DRC_STRIDE * DRC_HEIGHT; i++) {
|
|
DRC_FRAMEBUFFER[i] = col;
|
|
}
|
|
}
|
|
|
|
void gfx_draw_pixel(uint32_t x, uint32_t y, uint32_t col)
|
|
{
|
|
#ifdef DC_INIT
|
|
// both DC configurations use XRGB instead of RGBX
|
|
col >>= 8;
|
|
#endif
|
|
|
|
// put pixel in the drc buffer
|
|
uint32_t i = x + y * DRC_STRIDE;
|
|
if (i < DRC_STRIDE * DRC_HEIGHT) {
|
|
DRC_FRAMEBUFFER[i] = col;
|
|
}
|
|
|
|
// scale and put pixel in the tv buffer
|
|
for (uint32_t yy = (y * 1.5f); yy < ((y * 1.5f) + 1); yy++) {
|
|
for (uint32_t xx = (x * 1.5f); xx < ((x * 1.5f) + 1); xx++) {
|
|
uint32_t i = xx + yy * TV_STRIDE;
|
|
if (i < TV_STRIDE * TV_HEIGHT) {
|
|
TV_FRAMEBUFFER[i] = col;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void gfx_draw_rect_filled(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t col)
|
|
{
|
|
#ifdef DC_INIT
|
|
// both DC configurations use XRGB instead of RGBX
|
|
col >>= 8;
|
|
#endif
|
|
|
|
// DRC fill: normal scale
|
|
uint32_t* p = DRC_FRAMEBUFFER + (y * DRC_STRIDE) + x;
|
|
uint32_t stride_diff = DRC_STRIDE - w;
|
|
|
|
for (uint32_t hcnt = h; hcnt > 0; hcnt--) {
|
|
for (uint32_t wcnt = w; wcnt > 0; wcnt--) {
|
|
*p++ = col;
|
|
}
|
|
p += stride_diff;
|
|
}
|
|
|
|
// TV fill: 1.5x scale
|
|
p = TV_FRAMEBUFFER + ((uint32_t)(y * 1.5f) * TV_STRIDE) + (uint32_t)(x * 1.5f);
|
|
stride_diff = TV_STRIDE - (w * 1.5f);
|
|
|
|
for (uint32_t hcnt = (h * 1.5f); hcnt > 0; hcnt--) {
|
|
for (uint32_t wcnt = (w * 1.5f); wcnt > 0; wcnt--) {
|
|
*p++ = col;
|
|
}
|
|
p += stride_diff;
|
|
}
|
|
}
|
|
|
|
void gfx_draw_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t borderSize, uint32_t col)
|
|
{
|
|
gfx_draw_rect_filled(x, y, w, borderSize, col);
|
|
gfx_draw_rect_filled(x, y + h - borderSize, w, borderSize, col);
|
|
gfx_draw_rect_filled(x, y, borderSize, h, col);
|
|
gfx_draw_rect_filled(x + w - borderSize, y, borderSize, h, col);
|
|
}
|
|
|
|
void gfx_set_font_color(uint32_t col)
|
|
{
|
|
#ifdef DC_INIT
|
|
// both DC configurations use XRGB instead of RGBX
|
|
col >>= 8;
|
|
#endif
|
|
|
|
font_color = col;
|
|
}
|
|
|
|
uint32_t gfx_get_text_width(const char* string)
|
|
{
|
|
uint32_t i;
|
|
for (i = 0; *string; i++, string++);
|
|
return i * CHAR_SIZE_DRC_X;
|
|
}
|
|
|
|
static void gfx_draw_char(uint32_t x, uint32_t y, char c)
|
|
{
|
|
// Skip anything outside of [32,128), since the font doesn't have it.
|
|
if (c < 32 || c >= 128)
|
|
return;
|
|
c -= 32;
|
|
|
|
// DRC blit: Terminus 8x16 bold
|
|
const uint8_t* charDRC = font->ter_u16b[(unsigned char)c];
|
|
uint32_t *p = DRC_FRAMEBUFFER + (y * DRC_STRIDE) + x;
|
|
unsigned int stride_diff = DRC_STRIDE - CHAR_SIZE_DRC_X;
|
|
|
|
for (uint32_t hcnt = CHAR_SIZE_DRC_Y; hcnt > 0; hcnt--) {
|
|
uint8_t v = *charDRC++;
|
|
for (uint32_t wcnt = CHAR_SIZE_DRC_X; wcnt > 0; wcnt--, v >>= 1) {
|
|
if (v & 1) {
|
|
*p = font_color;
|
|
}
|
|
p++;
|
|
}
|
|
p += stride_diff;
|
|
}
|
|
|
|
// TV blit: Terminus 12x24 bold
|
|
const uint16_t* charTV = font->ter_u24b[(unsigned char)c];
|
|
p = TV_FRAMEBUFFER + ((uint32_t)(y * 1.5f) * TV_STRIDE) + (uint32_t)(x * 1.5f);
|
|
stride_diff = TV_STRIDE - CHAR_SIZE_TV_X;
|
|
|
|
for (uint32_t hcnt = CHAR_SIZE_TV_Y; hcnt > 0; hcnt--) {
|
|
uint16_t v = *charTV++;
|
|
for (uint32_t wcnt = CHAR_SIZE_TV_X; wcnt > 0; wcnt--, v >>= 1) {
|
|
if (v & 1) {
|
|
*p = font_color;
|
|
}
|
|
p++;
|
|
}
|
|
p += stride_diff;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Print text to the TV and DRC.
|
|
* Handles automatic newlines. ('\n' to go the next line)
|
|
* @param x X position
|
|
* @param y Y position
|
|
* @param gfxPrintFlags GfxPrintFlags
|
|
* @param str Text to print
|
|
* @return New Y position. (If no '\n' characters were included, same as the input y value.)
|
|
*/
|
|
uint32_t gfx_print(uint32_t x, uint32_t y, uint32_t gfxPrintFlags, const char* str)
|
|
{
|
|
const uint32_t orig_x = x;
|
|
|
|
if (gfxPrintFlags & GfxPrintFlag_AlignRight) {
|
|
x -= gfx_get_text_width(str);
|
|
}
|
|
if (gfxPrintFlags & GfxPrintFlag_ClearBG) {
|
|
gfx_draw_rect_filled(x, y, SCREEN_WIDTH, CHAR_SIZE_DRC_Y, COLOR_BACKGROUND);
|
|
}
|
|
|
|
for (; *str != '\0'; str++) {
|
|
const char chr = *str;
|
|
if ((unsigned char)chr >= 32 && (unsigned char)chr <= 128) {
|
|
gfx_draw_char(x, y, chr);
|
|
} else if (chr == '\n') {
|
|
// Newline; go to the start of the next line.
|
|
x = orig_x;
|
|
y += CHAR_SIZE_DRC_Y;
|
|
if (gfxPrintFlags & GfxPrintFlag_NewlinePlus4) {
|
|
y += 4;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if ((gfxPrintFlags & GfxPrintFlag_Underline) && (chr != '_')) {
|
|
gfx_draw_char(x, y, '_');
|
|
}
|
|
x += CHAR_SIZE_DRC_X;
|
|
}
|
|
|
|
return y;
|
|
}
|
|
|
|
/**
|
|
* Print text to the TV and DRC using printf()-style formatting.
|
|
*
|
|
* Handles automatic newlines. ('\n' to go the next line)
|
|
* NOTE: Automatic newlines might not work properly with AlignRight.
|
|
*
|
|
* @param x X position
|
|
* @param y Y position
|
|
* @param gfxPrintFlags GfxPrintFlags
|
|
* @param format printf()-style format
|
|
* @param ... Format parameters
|
|
* @return New Y position. (If no '\n' characters were included, same as the input y value.)
|
|
*/
|
|
uint32_t gfx_printf(uint32_t x, uint32_t y, uint32_t gfxPrintFlags, const char* format, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, format);
|
|
|
|
char buffer[0x100];
|
|
|
|
vsnprintf(buffer, sizeof(buffer), format, args);
|
|
y = gfx_print(x, y, gfxPrintFlags, buffer);
|
|
|
|
va_end(args);
|
|
|
|
return y;
|
|
}
|