diff --git a/source/gui/video.cpp b/source/gui/video.cpp index 1acc4f98..b5edc25e 100644 --- a/source/gui/video.cpp +++ b/source/gui/video.cpp @@ -6,7 +6,7 @@ #include "memory/mem2.hpp" #include "video.hpp" #include "pngu.h" -#include "Gekko.h" +#include "hw/Gekko.h" #include "gecko/gecko.hpp" #include "loader/sys.h" #include "loader/utils.h" @@ -526,8 +526,6 @@ void CVideo::_showWaitMessages(CVideo *m) m->prepare(); m->setup2DProjection(); - wiiLightSetLevel(0); - wiiLightOn(); //gprintf("Wait Message Thread: Start\nDelay: %d, Images: %d\n", waitFrames, m->m_waitMessages.size()); while(m->m_showWaitMessage) @@ -558,7 +556,6 @@ void CVideo::_showWaitMessages(CVideo *m) VIDEO_WaitVSync(); waitFrames--; } - wiiLightOff(); //gprintf("Wait Message Thread: End\n"); m->m_showingWaitMessages = false; } @@ -571,6 +568,7 @@ void CVideo::hideWaitMessage() m_showWaitMessage = false; if(waitThread != LWP_THREAD_NULL) { + /* end animation */ if(LWP_ThreadIsSuspended(waitThread)) LWP_ResumeThread(waitThread); while(m_showingWaitMessages) @@ -579,6 +577,8 @@ void CVideo::hideWaitMessage() if(waitMessageStack != NULL) MEM2_free(waitMessageStack); waitMessageStack = NULL; + /* end light thread */ + wiiLightEndThread(); m_WaitThreadRunning = false; } waitThread = LWP_THREAD_NULL; @@ -623,6 +623,10 @@ void CVideo::waitMessage(const vector &tex, float delay) waitMessage(m_waitMessages[0]); else if(m_waitMessages.size() > 1) { + /* changing light */ + wiiLightSetLevel(0); + wiiLightStartThread(); + /* onscreen animation */ m_showWaitMessage = true; if(waitMessageStack == NULL) waitMessageStack = (u8*)MEM2_memalign(32, waitMessageStackSize); diff --git a/source/gui/Gekko.c b/source/hw/Gekko.c similarity index 91% rename from source/gui/Gekko.c rename to source/hw/Gekko.c index b3e1ebfa..bf7f8eda 100644 --- a/source/gui/Gekko.c +++ b/source/hw/Gekko.c @@ -28,8 +28,6 @@ #include "Gekko.h" #include "memory/memory.h" -#define DISC_SLOT_LED 0x20 - lwp_t light_thread = LWP_THREAD_NULL; void *light_loop(); @@ -39,7 +37,18 @@ u8 light_level = 0; struct timespec light_timeon; struct timespec light_timeoff; +// Wii disc slot light routines void wiiLightOn() +{ + *HW_GPIOB_OUT |= DISC_SLOT_LED; +} + +void wiiLightOff() +{ + *HW_GPIOB_OUT &= ~DISC_SLOT_LED; +} + +void wiiLightStartThread() { light_on = true; light_level = 0; @@ -47,13 +56,14 @@ void wiiLightOn() LWP_CreateThread(&light_thread, light_loop, NULL, NULL, 0, LWP_PRIO_HIGHEST); } -void wiiLightOff() +void wiiLightEndThread() { light_on = false; light_level = 0; - LWP_JoinThread(light_thread, NULL); + if(light_thread != LWP_THREAD_NULL) + LWP_JoinThread(light_thread, NULL); light_thread = LWP_THREAD_NULL; - *HW_GPIOB_OUT &= ~DISC_SLOT_LED; + wiiLightOff(); } void wiiLightSetLevel(int level) @@ -89,11 +99,11 @@ void *light_loop() timeon = light_timeon; timeoff = light_timeoff; // Turn on the light and sleep for a bit - *HW_GPIOB_OUT |= DISC_SLOT_LED; + wiiLightOn(); nanosleep(&timeon); // Turn off the light (if required) and sleep for a bit if(timeoff.tv_nsec > 0) - *HW_GPIOB_OUT &= ~DISC_SLOT_LED; + wiiLightOff(); nanosleep(&timeoff); } return NULL; diff --git a/source/gui/Gekko.h b/source/hw/Gekko.h similarity index 92% rename from source/gui/Gekko.h rename to source/hw/Gekko.h index 60a65d44..b946721a 100644 --- a/source/gui/Gekko.h +++ b/source/hw/Gekko.h @@ -27,9 +27,13 @@ extern "C" { #endif +static const u32 DISC_SLOT_LED = 0x20; + // Wii disc slot light routines void wiiLightOn(); void wiiLightOff(); +void wiiLightStartThread(); +void wiiLightEndThread(); void wiiLightSetLevel(int level); #ifdef __cplusplus diff --git a/source/libwbfs/libwbfs.c b/source/libwbfs/libwbfs.c index 5e758c0c..4ca2c6af 100644 --- a/source/libwbfs/libwbfs.c +++ b/source/libwbfs/libwbfs.c @@ -40,7 +40,7 @@ static u8 size_to_shift(u32 size) wbfs_t *wbfs_open_hd(rw_sector_callback_t read_hdsector, rw_sector_callback_t write_hdsector, void *callback_data, int hd_sector_size, int num_hd_sector __attribute((unused)), int reset) { int i=num_hd_sector,ret; - u8 *ptr,*tmp_buffer = wbfs_ioalloc(hd_sector_size); + u8 *ptr,*tmp_buffer = wbfs_malloc(hd_sector_size); u8 part_table[16*4]; ret = read_hdsector(callback_data,0,1,tmp_buffer); if(ret) @@ -57,11 +57,11 @@ wbfs_t *wbfs_open_hd(rw_sector_callback_t read_hdsector, rw_sector_callback_t wr if (head->magic == wbfs_htonl(WBFS_MAGIC)) { wbfs_t *p = wbfs_open_partition(read_hdsector, write_hdsector, callback_data, hd_sector_size, 0, part_lba,reset); - wbfs_iofree(tmp_buffer); + wbfs_free(tmp_buffer); return p; } } - wbfs_iofree(tmp_buffer); + wbfs_free(tmp_buffer); if(reset)// XXX make a empty hd partition.. { } @@ -73,7 +73,7 @@ wbfs_t *wbfs_open_partition(rw_sector_callback_t read_hdsector, rw_sector_callba { wbfs_t *p = wbfs_malloc(sizeof(wbfs_t)); - wbfs_head_t *head = wbfs_ioalloc( hd_sector_size ? hd_sector_size : 512 ); + wbfs_head_t *head = wbfs_malloc( hd_sector_size ? hd_sector_size : 512 ); //constants, but put here for consistancy p->wii_sec_sz = 0x8000; @@ -131,20 +131,20 @@ wbfs_t *wbfs_open_partition(rw_sector_callback_t read_hdsector, rw_sector_callba else { // init with all free blocks - p->freeblks = wbfs_ioalloc(ALIGN_LBA( p->n_wbfs_sec / 8)); + p->freeblks = wbfs_malloc(ALIGN_LBA( p->n_wbfs_sec / 8)); wbfs_memset(p->freeblks, 0xff, p->n_wbfs_sec / 8); } p->max_disc = (p->freeblks_lba - 1) / (p->disc_info_sz >> p->hd_sec_sz_s); if(p->max_disc > p->hd_sec_sz - sizeof(wbfs_head_t)) p->max_disc = p->hd_sec_sz - sizeof(wbfs_head_t); - p->tmp_buffer = wbfs_ioalloc(p->hd_sec_sz); + p->tmp_buffer = wbfs_malloc(p->hd_sec_sz); p->n_disc_open = 0; return p; error: wbfs_free(p); - wbfs_iofree(head); + wbfs_free(head); return 0; } @@ -167,10 +167,10 @@ void wbfs_close(wbfs_t *p) if(p->n_disc_open) ERROR("trying to close wbfs while discs still open\n"); - wbfs_iofree(p->head); - wbfs_iofree(p->tmp_buffer); + wbfs_free(p->head); + wbfs_free(p->tmp_buffer); if(p->freeblks) - wbfs_iofree(p->freeblks); + wbfs_free(p->freeblks); wbfs_free(p); @@ -195,7 +195,7 @@ wbfs_disc_t *wbfs_open_disc(wbfs_t* p, const u8 *discid) ERROR("allocating memory\n"); d->p = p; d->i = i; - d->header = wbfs_ioalloc(p->disc_info_sz); + d->header = wbfs_malloc(p->disc_info_sz); if(!d->header) ERROR("allocating memory\n"); p->read_hdsector(p->callback_data, p->part_lba + 1 + i * disc_info_sz_lba, disc_info_sz_lba, d->header); @@ -209,13 +209,13 @@ wbfs_disc_t *wbfs_open_disc(wbfs_t* p, const u8 *discid) return 0; error: - if(d) wbfs_iofree(d); + if(d) wbfs_free(d); return 0; } void wbfs_close_disc(wbfs_disc_t*d) { d->p->n_disc_open --; - wbfs_iofree(d->header); + wbfs_free(d->header); wbfs_free(d); } // offset is pointing 32bit words to address the whole dvd, although len is in bytes @@ -349,10 +349,10 @@ u32 wbfs_get_disc_info(wbfs_t *p, u32 index,u8 *header,int header_size,u32 *size memcpy(header, p->tmp_buffer, header_size); if(size) { - u8 *header = wbfs_ioalloc(p->disc_info_sz); + u8 *header = wbfs_malloc(p->disc_info_sz); p->read_hdsector(p->callback_data, p->part_lba + 1 + i * disc_info_sz_lba, disc_info_sz_lba, header); u32 sec_used = wbfs_sector_used(p,(wbfs_disc_info_t *)header); - wbfs_iofree(header); + wbfs_free(header); *size = sec_used<<(p->wbfs_sec_sz_s-2); } return 0; @@ -367,7 +367,7 @@ static void load_freeblocks(wbfs_t *p) if(p->freeblks) return; // XXX should handle malloc error.. - p->freeblks = wbfs_ioalloc(ALIGN_LBA(p->n_wbfs_sec/8)); + p->freeblks = wbfs_malloc(ALIGN_LBA(p->n_wbfs_sec/8)); p->read_hdsector(p->callback_data, p->part_lba + p->freeblks_lba, ALIGN_LBA(p->n_wbfs_sec / 8) >> p->hd_sec_sz_s, p->freeblks); } @@ -476,10 +476,10 @@ u32 wbfs_add_disc(wbfs_t *p, read_wiidisc_callback_t read_src_wii_disc, void *ca load_freeblocks(p); // build disc info - info = wbfs_ioalloc(p->disc_info_sz); + info = wbfs_malloc(p->disc_info_sz); read_src_wii_disc(callback_data, 0, 0x100, info->disc_header_copy); - copy_buffer = wbfs_ioalloc(p->wii_sec_sz); + copy_buffer = wbfs_malloc(p->wii_sec_sz); if(!copy_buffer) ERROR("alloc memory\n"); tot = 0; @@ -568,9 +568,9 @@ error: if(used) wbfs_free(used); if(info) - wbfs_iofree(info); + wbfs_free(info); if(copy_buffer) - wbfs_iofree(copy_buffer); + wbfs_free(copy_buffer); // init with all free blocks return retval; @@ -622,7 +622,7 @@ u32 wbfs_size_disc(wbfs_t *p,read_wiidisc_callback_t read_src_wii_disc, u32 wii_sec_per_wbfs_sect = 1 << (p->wbfs_sec_sz_s - p->wii_sec_sz_s); wiidisc_t *d = 0; - u8 *used = wbfs_ioalloc(p->n_wii_sec_per_disc); + u8 *used = wbfs_malloc(p->n_wii_sec_per_disc); if(!used) ERROR("unable to alloc memory\n"); diff --git a/source/libwbfs/libwbfs_os.h b/source/libwbfs/libwbfs_os.h index c9844abb..4307800a 100644 --- a/source/libwbfs/libwbfs_os.h +++ b/source/libwbfs/libwbfs_os.h @@ -14,8 +14,22 @@ #include "loader/utils.h" #include "memory/mem2.hpp" -#define wbfs_fatal(x) do { gprintf(x); wd_last_error = 1; } while(0) -#define wbfs_error(x) do { gprintf(x); wd_last_error = 2; } while(0) +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +extern int wd_last_error; +static inline void wbfs_fatal(const char *x) +{ + gprintf(x); + wd_last_error = 1; +} + +static inline void wbfs_error(const char *x) +{ + gprintf(x); + wd_last_error = 2; +} static inline void *wbfs_malloc(size_t size) { @@ -29,8 +43,9 @@ static inline void wbfs_free(void *ptr) MEM2_free(ptr); } -#define wbfs_ioalloc(x) wbfs_malloc(x) -#define wbfs_iofree(x) wbfs_free(x) +#ifdef __cplusplus +} +#endif /* __cplusplus */ #define wbfs_be16(x) (*((u16*)(x))) #define wbfs_be32(x) (*((u32*)(x))) diff --git a/source/libwbfs/rijndael.c b/source/libwbfs/rijndael.c new file mode 100644 index 00000000..104d97df --- /dev/null +++ b/source/libwbfs/rijndael.c @@ -0,0 +1,445 @@ +/* Rijndael Block Cipher - rijndael.c + + Written by Mike Scott 21st April 1999 + mike@compapp.dcu.ie + + Permission for free direct or derivative use is granted subject + to compliance with any conditions that the originators of the + algorithm place on its exploitation. + + */ + +#include +#include +#include "gecko/gecko.hpp" +#include "loader/utils.h" +#define u8 unsigned char /* 8 bits */ +#define u32 unsigned long /* 32 bits */ +#define u64 unsigned long long + +/* rotates x one bit to the left */ + +#define ROTL(x) (((x)>>7)|((x)<<1)) + +/* Rotates 32-bit word left by 1, 2 or 3 byte */ + +#define ROTL8(x) (((x)<<8)|((x)>>24)) +#define ROTL16(x) (((x)<<16)|((x)>>16)) +#define ROTL24(x) (((x)<<24)|((x)>>8)) + +/* Fixed Data */ + +static u8 InCo[4] = { 0xB, 0xD, 0x9, 0xE }; /* Inverse Coefficients */ + +static u8 fbsub[256]; +static u8 rbsub[256]; +static u8 ptab[256], ltab[256]; +static u32 ftable[256]; +static u32 rtable[256]; +static u32 rco[30]; + +/* Parameter-dependent data */ + +int Nk, Nb, Nr; +u8 fi[24], ri[24]; +u32 fkey[120]; +u32 rkey[120]; + +static u32 pack(u8 *b) +{ /* pack bytes into a 32-bit Word */ + return ((u32 ) b[3] << 24) | ((u32 ) b[2] << 16) | ((u32 ) b[1] << 8) | (u32 ) b[0]; +} + +static void unpack(u32 a, u8 *b) +{ /* unpack bytes from a word */ + b[0] = (u8 ) a; + b[1] = (u8 ) (a >> 8); + b[2] = (u8 ) (a >> 16); + b[3] = (u8 ) (a >> 24); +} + +static u8 xtime(u8 a) +{ + u8 b; + if (a & 0x80) + b = 0x1B; + else b = 0; + a <<= 1; + a ^= b; + return a; +} + +static u8 bmul(u8 x, u8 y) +{ /* x.y= AntiLog(Log(x) + Log(y)) */ + if (x && y) + return ptab[(ltab[x] + ltab[y]) % 255]; + else return 0; +} + +static u32 SubByte(u32 a) +{ + u8 b[4]; + unpack(a, b); + b[0] = fbsub[b[0]]; + b[1] = fbsub[b[1]]; + b[2] = fbsub[b[2]]; + b[3] = fbsub[b[3]]; + return pack(b); +} + +static u8 product(u32 x, u32 y) +{ /* dot product of two 4-byte arrays */ + u8 xb[4], yb[4]; + unpack(x, xb); + unpack(y, yb); + return bmul(xb[0], yb[0]) ^ bmul(xb[1], yb[1]) ^ bmul(xb[2], yb[2]) ^ bmul(xb[3], yb[3]); +} + +static u32 InvMixCol(u32 x) +{ /* matrix Multiplication */ + u32 y, m; + u8 b[4]; + + m = pack(InCo); + b[3] = product(m, x); + m = ROTL24( m ); + b[2] = product(m, x); + m = ROTL24( m ); + b[1] = product(m, x); + m = ROTL24( m ); + b[0] = product(m, x); + y = pack(b); + return y; +} + +u8 ByteSub(u8 x) +{ + u8 y = ptab[255 - ltab[x]]; /* multiplicative inverse */ + x = y; + x = ROTL( x ); + y ^= x; + x = ROTL( x ); + y ^= x; + x = ROTL( x ); + y ^= x; + x = ROTL( x ); + y ^= x; + y ^= 0x63; + return y; +} + +void gentables(void) +{ /* generate tables */ + int i; + u8 y, b[4]; + + /* use 3 as primitive root to generate power and log tables */ + + ltab[0] = 0; + ptab[0] = 1; + ltab[1] = 0; + ptab[1] = 3; + ltab[3] = 1; + for (i = 2; i < 256; i++) + { + ptab[i] = ptab[i - 1] ^ xtime(ptab[i - 1]); + ltab[ptab[i]] = i; + } + + /* affine transformation:- each bit is xored with itself shifted one bit */ + + fbsub[0] = 0x63; + rbsub[0x63] = 0; + for (i = 1; i < 256; i++) + { + y = ByteSub((u8 ) i); + fbsub[i] = y; + rbsub[y] = i; + } + + for (i = 0, y = 1; i < 30; i++) + { + rco[i] = y; + y = xtime(y); + } + + /* calculate forward and reverse tables */ + for (i = 0; i < 256; i++) + { + y = fbsub[i]; + b[3] = y ^ xtime(y); + b[2] = y; + b[1] = y; + b[0] = xtime(y); + ftable[i] = pack(b); + + y = rbsub[i]; + b[3] = bmul(InCo[0], y); + b[2] = bmul(InCo[1], y); + b[1] = bmul(InCo[2], y); + b[0] = bmul(InCo[3], y); + rtable[i] = pack(b); + } +} + +void gkey(int nb, int nk, char *key) +{ /* blocksize=32*nb bits. Key=32*nk bits */ + /* currently nb,bk = 4, 6 or 8 */ + /* key comes as 4*Nk bytes */ + /* Key Scheduler. Create expanded encryption key */ + int i, j, k, m, N; + int C1, C2, C3; + u32 CipherKey[8]; + + Nb = nb; + Nk = nk; + + /* Nr is number of rounds */ + if (Nb >= Nk) + Nr = 6 + Nb; + else Nr = 6 + Nk; + + C1 = 1; + if (Nb < 8) + { + C2 = 2; + C3 = 3; + } + else + { + C2 = 3; + C3 = 4; + } + + /* pre-calculate forward and reverse increments */ + for (m = j = 0; j < nb; j++, m += 3) + { + fi[m] = (j + C1) % nb; + fi[m + 1] = (j + C2) % nb; + fi[m + 2] = (j + C3) % nb; + ri[m] = (nb + j - C1) % nb; + ri[m + 1] = (nb + j - C2) % nb; + ri[m + 2] = (nb + j - C3) % nb; + } + + N = Nb * (Nr + 1); + + for (i = j = 0; i < Nk; i++, j += 4) + { + CipherKey[i] = pack((u8 *) &key[j]); + } + for (i = 0; i < Nk; i++) + fkey[i] = CipherKey[i]; + for (j = Nk, k = 0; j < N; j += Nk, k++) + { + fkey[j] = fkey[j - Nk] ^ SubByte(ROTL24( fkey[j-1] )) ^ rco[k]; + if (Nk <= 6) + { + for (i = 1; i < Nk && (i + j) < N; i++) + fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1]; + } + else + { + for (i = 1; i < 4 && (i + j) < N; i++) + fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1]; + if ((j + 4) < N) fkey[j + 4] = fkey[j + 4 - Nk] ^ SubByte(fkey[j + 3]); + for (i = 5; i < Nk && (i + j) < N; i++) + fkey[i + j] = fkey[i + j - Nk] ^ fkey[i + j - 1]; + } + + } + + /* now for the expanded decrypt key in reverse order */ + + for (j = 0; j < Nb; j++) + rkey[j + N - Nb] = fkey[j]; + for (i = Nb; i < N - Nb; i += Nb) + { + k = N - Nb - i; + for (j = 0; j < Nb; j++) + rkey[k + j] = InvMixCol(fkey[i + j]); + } + for (j = N - Nb; j < N; j++) + rkey[j - N + Nb] = fkey[j]; +} + +/* There is an obvious time/space trade-off possible here. * + * Instead of just one ftable[], I could have 4, the other * + * 3 pre-rotated to save the ROTL8, ROTL16 and ROTL24 overhead */ + +void encrypt(char *buff) +{ + int i, j, k, m; + u32 a[8], b[8], *x, *y, *t; + + for (i = j = 0; i < Nb; i++, j += 4) + { + a[i] = pack((u8 *) &buff[j]); + a[i] ^= fkey[i]; + } + k = Nb; + x = a; + y = b; + + /* State alternates between a and b */ + for (i = 1; i < Nr; i++) + { /* Nr is number of rounds. May be odd. */ + + /* if Nb is fixed - unroll this next + loop and hard-code in the values of fi[] */ + + for (m = j = 0; j < Nb; j++, m += 3) + { /* deal with each 32-bit element of the State */ + /* This is the time-critical bit */ + y[j] = fkey[k++] ^ ftable[(u8 ) x[j]] ^ ROTL8( ftable[( u8 )( x[fi[m]] >> 8 )] ) + ^ ROTL16( ftable[( u8 )( x[fi[m+1]] >> 16 )] ) ^ ROTL24( ftable[x[fi[m+2]] >> 24] ); + } + t = x; + x = y; + y = t; /* swap pointers */ + } + + /* Last Round - unroll if possible */ + for (m = j = 0; j < Nb; j++, m += 3) + { + y[j] = fkey[k++] ^ (u32 ) fbsub[(u8 ) x[j]] ^ ROTL8( ( u32 )fbsub[( u8 )( x[fi[m]] >> 8 )] ) + ^ ROTL16( ( u32 )fbsub[( u8 )( x[fi[m+1]] >> 16 )] ) ^ ROTL24( ( u32 )fbsub[x[fi[m+2]] >> 24] ); + } + for (i = j = 0; i < Nb; i++, j += 4) + { + unpack(y[i], (u8 *) &buff[j]); + x[i] = y[i] = 0; /* clean up stack */ + } + return; +} + +void decrypt(char *buff) +{ + int i, j, k, m; + u32 a[8], b[8], *x, *y, *t; + + for (i = j = 0; i < Nb; i++, j += 4) + { + a[i] = pack((u8 *) &buff[j]); + a[i] ^= rkey[i]; + } + k = Nb; + x = a; + y = b; + + /* State alternates between a and b */ + for (i = 1; i < Nr; i++) + { /* Nr is number of rounds. May be odd. */ + + /* if Nb is fixed - unroll this next + loop and hard-code in the values of ri[] */ + + for (m = j = 0; j < Nb; j++, m += 3) + { /* This is the time-critical bit */ + y[j] = rkey[k++] ^ rtable[(u8 ) x[j]] ^ ROTL8( rtable[( u8 )( x[ri[m]] >> 8 )] ) + ^ ROTL16( rtable[( u8 )( x[ri[m+1]] >> 16 )] ) ^ ROTL24( rtable[x[ri[m+2]] >> 24] ); + } + t = x; + x = y; + y = t; /* swap pointers */ + } + + /* Last Round - unroll if possible */ + for (m = j = 0; j < Nb; j++, m += 3) + { + y[j] = rkey[k++] ^ (u32 ) rbsub[(u8 ) x[j]] ^ ROTL8( ( u32 )rbsub[( u8 )( x[ri[m]] >> 8 )] ) + ^ ROTL16( ( u32 )rbsub[( u8 )( x[ri[m+1]] >> 16 )] ) ^ ROTL24( ( u32 )rbsub[x[ri[m+2]] >> 24] ); + } + for (i = j = 0; i < Nb; i++, j += 4) + { + unpack(y[i], (u8 *) &buff[j]); + x[i] = y[i] = 0; /* clean up stack */ + } + return; +} + +void aes_set_key(const u8 *key) +{ + gentables(); + gkey(4, 4, (char*) key); +} + +// CBC mode decryption +void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, u64 len) +{ + u8 block[16]; + u32 blockno = 0, i; + + //printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len); + + for (blockno = 0; blockno <= (len / sizeof(block)); blockno++) + { + u32 fraction; + if (blockno == (len / sizeof(block))) // last block + { + fraction = len % sizeof(block); + if (fraction == 0) break; + memset(block, 0, sizeof(block)); + } + else fraction = 16; + + // debug_printf("block %d: fraction = %d\n", blockno, fraction); + memcpy(block, inbuf + blockno * sizeof(block), fraction); + decrypt((char*) block); + u8 *ctext_ptr; + if (blockno == 0) + ctext_ptr = iv; + else ctext_ptr = inbuf + (blockno - 1) * sizeof(block); + + for (i = 0; i < fraction; i++) + outbuf[blockno * sizeof(block) + i] = ctext_ptr[i] ^ block[i]; + // debug_printf("Block %d output: ", blockno); + // hexdump(outbuf + blockno*sizeof(block), 16); + } +} + +// CBC mode encryption +void aes_encrypt(u8 *iv, u8 *inbuf, u8 *outbuf, u64 len) +{ + u8 block[16]; + u32 blockno = 0, i; + + // debug_printf("aes_decrypt(%p, %p, %p, %lld)\n", iv, inbuf, outbuf, len); + + for (blockno = 0; blockno <= (len / sizeof(block)); blockno++) + { + u32 fraction; + if (blockno == (len / sizeof(block))) // last block + { + fraction = len % sizeof(block); + if (fraction == 0) break; + memset(block, 0, sizeof(block)); + } + else fraction = 16; + + // debug_printf("block %d: fraction = %d\n", blockno, fraction); + memcpy(block, inbuf + blockno * sizeof(block), fraction); + + for (i = 0; i < fraction; i++) + block[i] = inbuf[blockno * sizeof(block) + i] ^ iv[i]; + + encrypt((char*) block); + memcpy(iv, block, sizeof(block)); + memcpy(outbuf + blockno * sizeof(block), block, sizeof(block)); + // debug_printf("Block %d output: ", blockno); + // hexdump(outbuf + blockno*sizeof(block), 16); + } +} + + +// CBC mode decryption +#define WAD_BUF 0x10000 + +void aes_decrypt_partial(u8 *inbuf, u8 *outbuf, u8 block[16], u8 *ctext_ptr, u32 tmp_blockno) +{ + memcpy(block, inbuf + tmp_blockno * 16, 16); + decrypt((char*)block); + u32 i; + for(i = 0; i < 16; i++) + outbuf[tmp_blockno * 16 + i] = ctext_ptr[i] ^ block[i]; +} diff --git a/source/libwbfs/wiidisc.c b/source/libwbfs/wiidisc.c index ca26e039..666912d8 100644 --- a/source/libwbfs/wiidisc.c +++ b/source/libwbfs/wiidisc.c @@ -6,6 +6,10 @@ #include "wiidisc.h" #include "hw/aes.h" #include "loader/nk.h" +#include "loader/sys.h" + +void aes_set_key(const u8 *key); +void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, u64 len); int wd_last_error = 0; @@ -32,11 +36,19 @@ void decrypt_title_key(u8 *tik, u8 *title_key) wbfs_memset(iv, 0, sizeof iv); wbfs_memcpy(iv, tik + 0x01dc, 8); - AES_ResetEngine(); //check byte 0x1f1 in ticket to determine whether or not to use Korean Common Key //if value = 0x01, use Korean Common Key, else just use regular one - AES_EnableDecrypt((tik[0x01f1] == 1) ? korean_key : common_key, iv); - AES_Decrypt(tik + 0x01bf, title_key, 1); + if(Sys_HW_Access()) + { + AES_ResetEngine(); + AES_EnableDecrypt((tik[0x01f1] == 1) ? korean_key : common_key, iv); + AES_Decrypt(tik + 0x01bf, title_key, 1); + } + else + { + aes_set_key((tik[0x01f1] == 1) ? korean_key : common_key); + aes_decrypt(iv, tik + 0x01bf, title_key, 16); + } } static u32 _be32(const u8 *p) @@ -44,19 +56,22 @@ static u32 _be32(const u8 *p) return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; } -static void disc_read(wiidisc_t *d, u32 offset, u8 *data, u32 len) +static int disc_read(wiidisc_t *d, u32 offset, u8 *data, u32 len) { if (data) { int ret = 0; if (len == 0) - return; + return -1; ret = d->read(d->fp, offset, len, data); if(ret) + { wbfs_fatal("error reading disc\n"); + return -1; + } } - if (d->sector_usage_table) + if(d->sector_usage_table) { u32 blockno = offset >> 13; do @@ -66,35 +81,39 @@ static void disc_read(wiidisc_t *d, u32 offset, u8 *data, u32 len) if (len > 0x8000) len -= 0x8000; } while(len > 0x8000); } + return 0; } -static void partition_raw_read(wiidisc_t *d, u32 offset, u8 *data, u32 len) +static int partition_raw_read(wiidisc_t *d, u32 offset, u8 *data, u32 len) { - disc_read(d, d->partition_raw_offset + offset, data, len); + return disc_read(d, d->partition_raw_offset + offset, data, len); } -static void partition_read_block(wiidisc_t *d, u32 blockno, u8 *block) +static int partition_read_block(wiidisc_t *d, u32 blockno, u8 *block) { u8*raw = d->tmp_buffer; u8 iv[16]; u32 offset; if (d->sector_usage_table) d->sector_usage_table[d->partition_block+blockno] = 1; offset = d->partition_data_offset + ((0x8000 >> 2) * blockno); - partition_raw_read(d,offset, raw, 0x8000); + if(partition_raw_read(d,offset, raw, 0x8000) < 0) + return -1; memcpy(iv, raw + 0x3d0, 16); - + // decrypt data - if(neek2o()) + if(Sys_HW_Access()) { - NKAESDecryptBlock(raw, block); - } - else - { - AES_ResetEngine(); + AES_ResetEngine(); AES_EnableDecrypt(d->disc_key, iv); AES_Decrypt(raw + 0x400, block, 0x7c0); } + else + { + aes_set_key(d->disc_key); + aes_decrypt(iv, raw + 0x400, block, 0x7c00); + } + return 0; } static void partition_read(wiidisc_t *d, u32 offset, u8 *data, u32 len, int fake) @@ -111,7 +130,8 @@ static void partition_read(wiidisc_t *d, u32 offset, u8 *data, u32 len, int fake if (len_in_block > len) len_in_block = len; if (!fake) { - partition_read_block(d,offset / (0x7c00 >> 2), block); + if(partition_read_block(d,offset / (0x7c00 >> 2), block) < 0) + break; wbfs_memcpy(data, block + (offset_in_block << 2), len_in_block); } else d->sector_usage_table[d->partition_block + (offset / (0x7c00 >> 2))] = 1; @@ -151,7 +171,7 @@ static u32 do_fst(wiidisc_t *d, u8 *fst, const char *names, u32 i) offset = _be32(fst + 12 * i + 4); if (d->extract_pathname && strcasecmp(name, d->extract_pathname) == 0) { - d->extracted_buffer = wbfs_ioalloc(size); + d->extracted_buffer = wbfs_malloc(size); if (d->extracted_buffer != 0) { d->extracted_size = size; @@ -165,13 +185,13 @@ static u32 do_fst(wiidisc_t *d, u8 *fst, const char *names, u32 i) static void do_files(wiidisc_t*d) { - u8 *b = wbfs_ioalloc(0x480); // XXX: determine actual header size + u8 *b = wbfs_malloc(0x480); // XXX: determine actual header size u32 dol_offset; u32 fst_offset; u32 fst_size; u32 apl_offset; u32 apl_size; - u8 *apl_header = wbfs_ioalloc(0x20); + u8 *apl_header = wbfs_malloc(0x20); u8 *fst; u32 n_files; partition_read(d, 0, b, 0x480, 0); @@ -189,7 +209,7 @@ static void do_files(wiidisc_t*d) if (fst_size) { - fst = wbfs_ioalloc(fst_size); + fst = wbfs_malloc(fst_size); if (fst == 0) wbfs_fatal("malloc fst\n"); partition_read(d, fst_offset, fst, fst_size,0); @@ -209,16 +229,16 @@ static void do_files(wiidisc_t*d) if (12 * n_files <= fst_size) if (n_files > 1) do_fst(d, fst, (char *)fst + 12 * n_files, 0); - if (fst != d->extracted_buffer) wbfs_iofree( fst ); + if (fst != d->extracted_buffer) wbfs_free( fst ); } - wbfs_iofree(b); - wbfs_iofree(apl_header); + wbfs_free(b); + wbfs_free(apl_header); } static void do_partition(wiidisc_t*d) { - u8 *tik = wbfs_ioalloc(0x2a4); - u8 *b = wbfs_ioalloc(0x1c); + u8 *tik = wbfs_malloc(0x2a4); + u8 *b = wbfs_malloc(0x1c); u64 tmd_offset; u32 tmd_size; u8 *tmd; @@ -238,7 +258,7 @@ static void do_partition(wiidisc_t*d) h3_offset = _be32(b + 0x10); d->partition_data_offset = _be32(b + 0x14); d->partition_block = (d->partition_raw_offset + d->partition_data_offset) >> 13; - tmd = wbfs_ioalloc(tmd_size); + tmd = wbfs_malloc(tmd_size); if (tmd == 0) wbfs_fatal("malloc tmd\n"); partition_raw_read(d, tmd_offset, tmd, tmd_size); @@ -249,24 +269,20 @@ static void do_partition(wiidisc_t*d) d->extracted_size = tmd_size; } - cert = wbfs_ioalloc(cert_size); + cert = wbfs_malloc(cert_size); if (cert == 0) wbfs_fatal("malloc cert\n"); partition_raw_read(d, cert_offset, cert, cert_size); - - if(neek2o()) - NKKeyCreate(tik); - else - decrypt_title_key(tik, d->disc_key); + decrypt_title_key(tik, d->disc_key); partition_raw_read(d, h3_offset, 0, 0x18000); - wbfs_iofree(b); - wbfs_iofree(tik); - wbfs_iofree(cert); + wbfs_free(b); + wbfs_free(tik); + wbfs_free(cert); if(tmd != d->extracted_buffer) - wbfs_iofree( tmd ); + wbfs_free( tmd ); do_files(d); @@ -284,22 +300,25 @@ static int test_parition_skip(u32 partition_type, partition_selector_t part_sel) default: return (partition_type != part_sel); } -} +} + static void do_disc(wiidisc_t *d) { - u8 *b = wbfs_ioalloc(0x100); + u8 *b = wbfs_malloc(0x100); + if(b == NULL) + goto out; u64 partition_offset[32]; // XXX: don't know the real maximum u64 partition_type[32]; // XXX: don't know the real maximum u32 n_partitions; u32 magic; u32 i; - disc_read(d, 0, b, 0x100); + if(disc_read(d, 0, b, 0x100) < 0) + goto out; magic = _be32(b + 24); if (magic != WII_MAGIC) { - wbfs_iofree(b); wbfs_error("not a wii disc"); - return ; + goto out; } disc_read(d, 0x40000 >> 2, b, 0x100); n_partitions = _be32(b); @@ -314,7 +333,8 @@ static void do_disc(wiidisc_t *d) d->partition_raw_offset = partition_offset[i]; if (!test_parition_skip(partition_type[i], d->part_sel)) do_partition(d); } - wbfs_iofree(b); +out: + wbfs_free(b); } wiidisc_t *wd_open_disc(read_wiidisc_callback_t read, void *fp) @@ -325,19 +345,19 @@ wiidisc_t *wd_open_disc(read_wiidisc_callback_t read, void *fp) d->read = read; d->fp = fp; d->part_sel = ALL_PARTITIONS; - d->tmp_buffer = wbfs_ioalloc(0x8000); - d->tmp_buffer2 = wbfs_ioalloc(0x8000); + d->tmp_buffer = wbfs_malloc(0x8000); + d->tmp_buffer2 = wbfs_malloc(0x8000); return d; } void wd_close_disc(wiidisc_t *d) { - wbfs_iofree(d->tmp_buffer); + wbfs_free(d->tmp_buffer); wbfs_free(d->tmp_buffer2); wbfs_free(d); } -// returns a buffer allocated with wbfs_ioalloc() or NULL if not found of alloc error +// returns a buffer allocated with wbfs_malloc() or NULL if not found of alloc error // XXX pathname not implemented. files are extracted by their name. // first file found with that name is returned. u8 *wd_extract_file(wiidisc_t *d, u32 *size, partition_selector_t partition_type, const char *pathname) diff --git a/source/loader/gc_disc_dump.cpp b/source/loader/gc_disc_dump.cpp index 6085ff78..78e601f1 100644 --- a/source/loader/gc_disc_dump.cpp +++ b/source/loader/gc_disc_dump.cpp @@ -36,7 +36,7 @@ #include "devicemounter/DeviceHandler.hpp" #include "fileOps/fileOps.h" #include "gecko/gecko.hpp" -#include "gui/Gekko.h" +#include "hw/Gekko.h" #include "gui/text.hpp" #include "memory/mem2.hpp" #include "menu/menu.hpp" @@ -69,7 +69,6 @@ void GCDump::__AnalizeMultiDisc() s32 GCDump::__DiscReadRaw(void *outbuf, u64 offset, u32 length) { length = ALIGN32(length); - wiiLightSetLevel(255); wiiLightOn(); while(1) { @@ -179,7 +178,6 @@ bool GCDump::__WaitForDisc(u8 dsc, u32 msg) mainMenu.GC_Messenger(msg, dsc+1, minfo); while(1) { - wiiLightSetLevel(255); wiiLightOn(); usleep(1000000); wiiLightOff(); @@ -191,7 +189,6 @@ bool GCDump::__WaitForDisc(u8 dsc, u32 msg) while(1) { - wiiLightSetLevel(255); wiiLightOn(); usleep(1000000); wiiLightOff(); diff --git a/source/loader/nk.c b/source/loader/nk.c index ec4bddb4..b8055bc8 100644 --- a/source/loader/nk.c +++ b/source/loader/nk.c @@ -29,12 +29,13 @@ #include #include "nk.h" +#include "sys.h" #include "armboot.h" #include "fileOps/fileOps.h" #include "memory/mem2.hpp" #include "gecko/gecko.hpp" -static u32 KeyID; +//static u32 KeyID; bool checked = false; bool neek = false; u32 kernelSize = 0; @@ -45,6 +46,8 @@ void check_neek2o(void) if(checked == true) return; checked = true; + if(Sys_DolphinMode() == true) + return; s32 ESHandle = IOS_Open("/dev/es", 0); neek = (IOS_Ioctlv(ESHandle, 0xA2, 0, 0, NULL) == 0x666c6f77); @@ -133,7 +136,7 @@ s32 Launch_nk(u64 TitleID, const char *nandpath, u64 ReturnTo) MEM1_free(mini); return 1; } - +/* void NKKeyCreate(u8 *tik) { u32 *TKeyID = (u32*)MEM1_memalign(32, sizeof(u32)); @@ -185,3 +188,4 @@ void NKAESDecryptBlock(u8 *in, u8 *out) IOS_Ioctlv(ESHandle, 0x2D, 3, 2, (ioctlv *)v); IOS_Close(ESHandle); } +*/ \ No newline at end of file diff --git a/source/loader/nk.h b/source/loader/nk.h index a02677ef..4073a0e8 100644 --- a/source/loader/nk.h +++ b/source/loader/nk.h @@ -29,8 +29,8 @@ s32 Launch_nk(u64 TitleID, const char *nandpath, u64 ReturnTo); bool Load_Neek2o_Kernel(); void check_neek2o(void); bool neek2o(void); -void NKKeyCreate(u8 *TIK); -void NKAESDecryptBlock(u8 *in, u8 *out); +/*void NKKeyCreate(u8 *TIK); +void NKAESDecryptBlock(u8 *in, u8 *out);*/ #ifdef __cplusplus } diff --git a/source/loader/splits.c b/source/loader/splits.c index 910e4176..12d3e158 100644 --- a/source/loader/splits.c +++ b/source/loader/splits.c @@ -18,7 +18,10 @@ #define FMT_llu "%llu" #define FMT_lld "%lld" -#define split_error(x) do { gprintf("\nsplit error: %s\n\n",x); } while(0) +static inline void split_error(const char *x) +{ + gprintf("\nsplit error: %s\n\n",x); +} // 1 cluster less than 4gb u64 OPT_split_size = (u64)4LL * 1024 * 1024 * 1024 - 32 * 1024; diff --git a/source/loader/sys.c b/source/loader/sys.c index 0d27eefa..99dcd026 100644 --- a/source/loader/sys.c +++ b/source/loader/sys.c @@ -205,5 +205,18 @@ bool Sys_DolphinMode(void) return DolphinMode; } +bool hw_check = false; +bool on_hw = false; +bool Sys_HW_Access(void) +{ + if(hw_check == true) + return on_hw; + + check_neek2o(); + on_hw = AHBRPOT_Patched() && (!Sys_DolphinMode() && !neek2o()); + hw_check = true; + return on_hw; +} + /* KILL IT */ s32 __IOS_LoadStartupIOS() { return 0; } diff --git a/source/loader/sys.h b/source/loader/sys.h index 8ed56fd7..5551d45b 100644 --- a/source/loader/sys.h +++ b/source/loader/sys.h @@ -32,6 +32,7 @@ enum /* Prototypes */ void Sys_Init(void); bool Sys_DolphinMode(void); +bool Sys_HW_Access(void); bool Sys_Exiting(void); void Sys_Exit(void); void Sys_ExitTo(int); diff --git a/source/memory/mem2.cpp b/source/memory/mem2.cpp index 0644ffb0..7d9d11ea 100644 --- a/source/memory/mem2.cpp +++ b/source/memory/mem2.cpp @@ -2,25 +2,28 @@ #include #include #include +#include #include "mem2.hpp" -#include "mem2alloc.hpp" +#include "mem_manager.hpp" #include "gecko/gecko.hpp" #include "loader/utils.h" -#define MEM2_PRIORITY_SIZE 0x1000 +static const u32 MEM2_PRIORITY_SIZE = 0x1000; // Forbid the use of MEM2 through malloc u32 MALLOC_MEM2 = 0; -void *MEM1_lo_start = (void*)0x80004000; -void *MEM1_lo_end = (void*)0x80620000; +u8 *MEM1_lo_start = (u8*)0x80004000; +u8 *MEM1_lo_end = (u8*)0x80620000; +u8 *MEM1_lo_list = (u8*)0x93280000; -void *MEM2_start = (void*)0x90200000; -void *MEM2_end = (void*)0x93100000; +u8 *MEM2_start = (u8*)0x90200000; +u8 *MEM2_end = (u8*)0x93200000; +u8 *MEM2_list = (u8*)0x93200000; -static CMEM2Alloc g_mem1lo; -static CMEM2Alloc g_mem2gp; +MemManager g_mem1lo; +MemManager g_mem2gp; extern "C" { @@ -34,23 +37,25 @@ extern __typeof(malloc_usable_size) __real_malloc_usable_size; void MEM_init() { - g_mem1lo.init(MEM1_lo_start, MEM1_lo_end); //about 6mb - g_mem1lo.clear(); + MemMutexInit(); - g_mem2gp.init(MEM2_start, MEM2_end); //about 47mb - g_mem2gp.clear(); + g_mem1lo.Init(MEM1_lo_start, MEM1_lo_list, (u32)(MEM1_lo_end-MEM1_lo_start)); //about 6mb + g_mem1lo.ClearMem(); + + g_mem2gp.Init(MEM2_start, MEM2_list, (u32)(MEM2_end-MEM2_start)); //about 48mb + g_mem2gp.ClearMem(); } void *MEM1_lo_alloc(unsigned int s) { - return g_mem1lo.allocate(s); + return g_mem1lo.Alloc(s); } void MEM1_lo_free(void *p) { if(!p) return; - g_mem1lo.release(p); + g_mem1lo.Free(p); } unsigned int MEM1_lo_freesize() @@ -91,28 +96,28 @@ void MEM2_free(void *p) { if(!p) return; - g_mem2gp.release(p); + g_mem2gp.Free(p); } void *MEM2_alloc(unsigned int s) { - return g_mem2gp.allocate(s); + return g_mem2gp.Alloc(s); } /* Placeholder, will be needed with new memory manager */ void *MEM2_memalign(unsigned int /* alignment */, unsigned int s) { - return MEM2_alloc(s); + return g_mem2gp.Alloc(s); } void *MEM2_realloc(void *p, unsigned int s) { - return g_mem2gp.reallocate(p, s); + return g_mem2gp.ReAlloc(p, s); } unsigned int MEM2_usableSize(void *p) { - return g_mem2gp.usableSize(p); + return g_mem2gp.MemBlockSize(p); } unsigned int MEM2_freesize() @@ -125,7 +130,7 @@ void *__wrap_malloc(size_t size) void *p; if(size >= MEM2_PRIORITY_SIZE) { - p = g_mem2gp.allocate(size); + p = g_mem2gp.Alloc(size); if(p != 0) return p; return __real_malloc(size); @@ -133,7 +138,7 @@ void *__wrap_malloc(size_t size) p = __real_malloc(size); if(p != 0) return p; - return g_mem2gp.allocate(size); + return g_mem2gp.Alloc(size); } void *__wrap_calloc(size_t n, size_t size) @@ -141,7 +146,7 @@ void *__wrap_calloc(size_t n, size_t size) void *p; if((n * size) >= MEM2_PRIORITY_SIZE) { - p = g_mem2gp.allocate(n * size); + p = g_mem2gp.Alloc(n * size); if (p != 0) { memset(p, 0, n * size); @@ -153,7 +158,7 @@ void *__wrap_calloc(size_t n, size_t size) p = __real_calloc(n, size); if (p != 0) return p; - p = g_mem2gp.allocate(n * size); + p = g_mem2gp.Alloc(n * size); if (p != 0) memset(p, 0, n * size); return p; @@ -166,7 +171,7 @@ void *__wrap_memalign(size_t a, size_t size) { if(a <= 32 && 32 % a == 0) { - p = g_mem2gp.allocate(size); + p = g_mem2gp.Alloc(size); if (p != 0) return p; } @@ -176,7 +181,7 @@ void *__wrap_memalign(size_t a, size_t size) if(p != 0 || a > 32 || 32 % a != 0) return p; - return g_mem2gp.allocate(size); + return g_mem2gp.Alloc(size); } void __wrap_free(void *p) @@ -187,9 +192,9 @@ void __wrap_free(void *p) if(((u32)p & 0x10000000) != 0) { //if(p > MEM2_start) - g_mem2gp.release(p); + g_mem2gp.Free(p); //else - //g_mem2lo_gp.release(p); + //g_mem2lo_gp.Free(p); } else MEM1_free(p); @@ -201,7 +206,7 @@ void *__wrap_realloc(void *p, size_t size) // ptr from mem2 if(((u32)p & 0x10000000) != 0 || (p == 0 && size > MEM2_PRIORITY_SIZE)) { - n = g_mem2gp.reallocate(p, size); + n = g_mem2gp.ReAlloc(p, size); if(n != 0) return n; n = __real_malloc(size); @@ -210,7 +215,7 @@ void *__wrap_realloc(void *p, size_t size) if(p != 0) { memcpy(n, p, MEM2_usableSize(p) < size ? MEM2_usableSize(p) : size); - g_mem2gp.release(p); + g_mem2gp.Free(p); } return n; } @@ -218,7 +223,7 @@ void *__wrap_realloc(void *p, size_t size) n = __real_realloc(p, size); if(n != 0) return n; - n = g_mem2gp.allocate(size); + n = g_mem2gp.Alloc(size); if(n == 0) return 0; if(p != 0) @@ -232,7 +237,7 @@ void *__wrap_realloc(void *p, size_t size) size_t __wrap_malloc_usable_size(void *p) { if(((u32)p & 0x10000000) != 0) - return CMEM2Alloc::usableSize(p); + return g_mem2gp.MemBlockSize(p); return __real_malloc_usable_size(p); } diff --git a/source/memory/mem2.hpp b/source/memory/mem2.hpp index 0ec7e5eb..eb61ca96 100644 --- a/source/memory/mem2.hpp +++ b/source/memory/mem2.hpp @@ -1,5 +1,3 @@ -// 1 MEM2 allocator, one for general purpose -// Aligned and padded to 32 bytes, as required by many functions #ifndef __MEM2_HPP #define __MEM2_HPP diff --git a/source/memory/mem2alloc.cpp b/source/memory/mem2alloc.cpp deleted file mode 100644 index d9c82003..00000000 --- a/source/memory/mem2alloc.cpp +++ /dev/null @@ -1,230 +0,0 @@ -#include "mem2alloc.hpp" - -#include -#include -#include -#include -#include "lockMutex.hpp" -#include "gecko/gecko.hpp" -void CMEM2Alloc::init(void *addr, void *end) -{ - m_baseAddress = (SBlock *)(((u32)addr + 31) & ~31); - m_endAddress = (SBlock *)((u32)end & ~31); - LWP_MutexInit(&m_mutex, 0); -} - -void CMEM2Alloc::cleanup(void) -{ - LWP_MutexDestroy(m_mutex); - m_mutex = 0; - m_first = 0; - // Try to release the range we took through SYS functions - /*if (SYS_GetArena2Lo() == m_endAddress) - SYS_SetArena2Lo(m_baseAddress);*/ - m_baseAddress = 0; - m_endAddress = 0; -} - -void CMEM2Alloc::clear(void) -{ - m_first = 0; - u32 Size = (u32)m_endAddress - (u32)m_baseAddress; - memset(m_baseAddress, 0, Size); - DCFlushRange(m_baseAddress, Size); -} - -unsigned int CMEM2Alloc::usableSize(void *p) -{ - return p == 0 ? 0 : ((SBlock *)p - 1)->s * sizeof (SBlock); -} - -bool CMEM2Alloc::is_valid(const SBlock *block) -{ - if((u32)block >= (u32)m_baseAddress && (u32)block < (u32)m_endAddress) - return true; - gprintf("WARNING: Found invalid memory location!\n"); - return false; -} - -void *CMEM2Alloc::allocate(unsigned int s) -{ - if (s == 0) - s = 1; - // - LockMutex lock(m_mutex); - // - s = (s - 1) / sizeof (SBlock) + 1; - // First block - if (m_first == 0) - { - if (m_baseAddress + s + 1 >= m_endAddress) - return 0; - m_first = m_baseAddress; - m_first->next = 0; - m_first->prev = 0; - m_first->s = s; - m_first->f = false; - return (void *)(m_first + 1); - } - // Search for a free block - SBlock *i; - SBlock *j = m_first; - for (i = m_first; i != 0; i = i->next) - { - if (i->f && i->s >= s) - break; - j = i; - } - // Create a new block - if (i == 0) - { - i = j + j->s + 1; - if (i + s + 1 >= m_endAddress) - return 0; - j->next = i; - i->prev = j; - i->next = 0; - i->s = s; - i->f = false; - return (void *)(i + 1); - } - // Reuse a free block - i->f = false; - // Split it - if (i->s > s + 1) - { - j = i + s + 1; - j->f = true; - j->s = i->s - s - 1; - i->s = s; - j->next = i->next; - j->prev = i; - i->next = j; - if(j->next != 0 && is_valid(j->next)) - j->next->prev = j; - } - return (void *)(i + 1); -} - -void CMEM2Alloc::release(void *p) -{ - if (p == 0) - return; - - LockMutex lock(m_mutex); - SBlock *i = (SBlock *)p - 1; - i->f = true; - - // If there are no other blocks following yet, - // set the remaining size to free size. - Dimok - if(i->next == 0) - i->s = m_endAddress - i - 1; - - // Merge with previous block - if (i->prev != 0 && is_valid(i->prev) && is_valid(i->prev->next) && i->prev->f) - { - i = i->prev; - i->s += i->next->s + 1; - if(i->next->next != 0 && is_valid(i->next->next)) - { - i->next = i->next->next; - i->next->prev = i; - } - } - // Merge with next block - if (i->next != 0 && is_valid(i->next) && i->next->f) - { - i->s += i->next->s + 1; - i->next = i->next->next; - if(i->next != 0 && is_valid(i->next)) - i->next->prev = i; - } -} - -void *CMEM2Alloc::reallocate(void *p, unsigned int s) -{ - SBlock *i; - SBlock *j; - void *n; - - if (s == 0) - s = 1; - if (p == 0) - return allocate(s); - - i = (SBlock *)p - 1; - s = (s - 1) / sizeof (SBlock) + 1; - - LockMutex lock(m_mutex); - - //out of memory /* Dimok */ - if (i + s + 1 >= m_endAddress) - { - return 0; - } - - // Last block - if (i->next == 0 && i + s + 1 < m_endAddress) - { - i->s = s; - return p; - } - // Size <= current size + next block - if (i->next != 0 && is_valid(i->next) && i->s < s && i->next->f && i->s + i->next->s + 1 >= s) - { - // Merge - i->s += i->next->s + 1; - i->next = i->next->next; - if(i->next != 0 && is_valid(i->next)) - i->next->prev = i; - } - // Size <= current size - if (i->s >= s) - { - // Split - if (i->s > s + 1) - { - j = i + s + 1; - j->f = true; - j->s = i->s - s - 1; - i->s = s; - j->next = i->next; - j->prev = i; - i->next = j; - if(j->next != 0 && is_valid(j->next)) - j->next->prev = j; - } - return p; - } - - // Size > current size - n = allocate(s * sizeof (SBlock)); - if (n == 0) - return 0; - memcpy(n, p, i->s * sizeof (SBlock)); - release(p); - return n; -} - -unsigned int CMEM2Alloc::FreeSize() -{ - LockMutex lock(m_mutex); - - if (m_first == 0) - return (u32)m_endAddress - (u32)m_baseAddress; - - SBlock *i; - unsigned int size = 0; - - for(i = m_first; i != 0; i = i->next) - { - if(i->f && i->next != 0 && is_valid(i->next)) - size += i->s; - else if(i->f && i->next == 0) - size += m_endAddress - i - 1; - else if(!i->f && i->next == 0) - size += m_endAddress - i - i->s - 1; - } - - return size*sizeof(SBlock); -} diff --git a/source/memory/mem2alloc.hpp b/source/memory/mem2alloc.hpp deleted file mode 100644 index 209fd7af..00000000 --- a/source/memory/mem2alloc.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// MEM2 allocator -// Made as a class so i can have 2 sections, one being dedicated to the covers - -#ifndef __MEM2ALLOC_HPP -#define __MEM2ALLOC_HPP - -#include - -class CMEM2Alloc -{ -public: - void *allocate(unsigned int s); - void release(void *p); - void *reallocate(void *p, unsigned int s); - void init(unsigned int size); - void init(void *addr, void *end); - void cleanup(void); - void clear(void); - static unsigned int usableSize(void *p); - void forceEndAddress(void *newAddr) { m_endAddress = (SBlock *)newAddr; } - void *getEndAddress(void) const { return m_endAddress; } - void info(void *&address, unsigned int &size) const { address = m_baseAddress; size = (const char *)m_endAddress - (const char *)m_baseAddress; } - unsigned int FreeSize(); - // - CMEM2Alloc(void) : m_baseAddress(0), m_endAddress(0), m_first(0), m_mutex(0) { } -private: - struct SBlock - { - unsigned int s; - SBlock *next; - SBlock *prev; - bool f; - } __attribute__((aligned(32))); - bool is_valid(const SBlock *block); - SBlock *m_baseAddress; - SBlock *m_endAddress; - SBlock *m_first; - mutex_t m_mutex; -private: - CMEM2Alloc(const CMEM2Alloc &); -}; - -#endif // !defined(__MEM2ALLOC_HPP) diff --git a/source/memory/mem_manager.cpp b/source/memory/mem_manager.cpp new file mode 100644 index 00000000..c143930e --- /dev/null +++ b/source/memory/mem_manager.cpp @@ -0,0 +1,194 @@ +/**************************************************************************** + * Copyright (C) 2013 FIX94 + * + * 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 . + ****************************************************************************/ +#include +#include +#include "mem_manager.hpp" +#include "gecko/gecko.hpp" +#include "loader/utils.h" + +static mutex_t memMutex = 0; +static const u32 MEM_BLOCK_SIZE = 256; + +void MemMutexInit() +{ + LWP_MutexInit(&memMutex, 0); +} + +void MemMutexDestroy() +{ + LWP_MutexDestroy(memMutex); + memset(&memMutex, 0, sizeof(mutex_t)); +} + +MemManager::MemManager() +{ + startAddr = NULL; + memList = NULL; + memListEnd = NULL; + memSize = 0; +} + +void MemManager::Init(u8 *start, u8 *list, u32 size) +{ + LWP_MutexLock(memMutex); + //gprintf("Init %x %i\n", memList, memSize); + + startAddr = start; + memList = list; + memSize = ALIGN(MEM_BLOCK_SIZE, size) / MEM_BLOCK_SIZE; + memListEnd = list + memSize; + ICInvalidateRange(memList, memSize+1); + memset(memList, MEM_FREE , memSize); + memset(memListEnd, MEM_END, 1); //thats the +1 + DCFlushRange(memList, memSize+1); + + LWP_MutexUnlock(memMutex); +} + +void MemManager::ClearMem() +{ + LWP_MutexLock(memMutex); + //gprintf("ClearMem %x %i\n", startAddr, memSize * MEM_BLOCK_SIZE); + + u32 MemFull = memSize * MEM_BLOCK_SIZE; + ICInvalidateRange(startAddr, MemFull); + memset(startAddr, 0, MemFull); + DCFlushRange(startAddr, MemFull); + + LWP_MutexUnlock(memMutex); +} + +void *MemManager::Alloc(u32 size) +{ + size = ALIGN(MEM_BLOCK_SIZE, size) / MEM_BLOCK_SIZE; + if(size > memSize) + return NULL; + + LWP_MutexLock(memMutex); + + vu8 *tmp_block; + u32 blocksFree; + for(vu8 *block = memList; block < memListEnd; block++) + { + for( ; *block & (ALLOC_USED | ALLOC_END); block++) ; + blocksFree = 0; + for(tmp_block = block; *tmp_block == MEM_FREE; tmp_block++) + { + blocksFree++; + if(blocksFree == size) + { + u8 *addr = (u8*)block; + ICInvalidateRange(addr, blocksFree); + memset(addr, ALLOC_USED, blocksFree - 1); //start blocks + memset(addr + blocksFree - 1, ALLOC_END, 1); //end block + DCFlushRange(addr, blocksFree); + void *ptr = (void*)(startAddr + ((addr - memList)*MEM_BLOCK_SIZE)); + //gprintf("Alloc %x mem, %i blocks\n", ptr, blocksFree); + LWP_MutexUnlock(memMutex); + return ptr; + } + } + block = tmp_block; + } + LWP_MutexUnlock(memMutex); + return NULL; +} + +void MemManager::Free(void *mem) +{ + vu8 *blockUsed = memList+(((u8*)mem-startAddr) / MEM_BLOCK_SIZE); + if(blockUsed < memList || blockUsed >= memListEnd || *blockUsed == 0) + return; + + LWP_MutexLock(memMutex); + + //gprintf("Free %x mem, %x block\n", mem, blockUsed); + + u32 size = 0; + vu8 *tmp_block = blockUsed; + for( ; *tmp_block == ALLOC_USED; tmp_block++) + size++; + if(*tmp_block == ALLOC_END) + size++; + + u8 *addr = (u8*)blockUsed; + ICInvalidateRange(addr, size); + memset(addr, MEM_FREE, size); + DCFlushRange(addr, size); + + LWP_MutexUnlock(memMutex); +} + +u32 MemManager::MemBlockSize(void *mem) +{ + vu8 *blockUsed = memList+(((u8*)mem-startAddr) / MEM_BLOCK_SIZE); + if(blockUsed < memList || blockUsed >= memListEnd || *blockUsed == 0) + return 0; + + LWP_MutexLock(memMutex); + + u32 size = 0; + for( ; *blockUsed == ALLOC_USED; blockUsed++) + size++; + if(*blockUsed == ALLOC_END) + size++; + size *= MEM_BLOCK_SIZE; + + LWP_MutexUnlock(memMutex); + + return size; +} + +u32 MemManager::FreeSize() +{ + LWP_MutexLock(memMutex); + + u32 free = 0; + for(vu8 *block = memList; block < memListEnd; block++) + { + for( ; *block == MEM_FREE; block++) + free++; + } + free *= MEM_BLOCK_SIZE; + + LWP_MutexUnlock(memMutex); + + return free; +} + +void *MemManager::ReAlloc(void *mem, u32 size) +{ + if(mem == NULL) + return Alloc(size); + + //gprintf("Realloc %x, %i\n", mem, size); + void *new_m = Alloc(size); + if(new_m == NULL) + { + Free(mem); + return NULL; + } + const u32 copysize = std::min(MemBlockSize(mem), size); + + LWP_MutexLock(memMutex); + memcpy(new_m, mem, copysize); + LWP_MutexUnlock(memMutex); + + Free(mem); + + return new_m; +} diff --git a/source/memory/mem_manager.hpp b/source/memory/mem_manager.hpp new file mode 100644 index 00000000..96fd4de1 --- /dev/null +++ b/source/memory/mem_manager.hpp @@ -0,0 +1,51 @@ +/**************************************************************************** + * Copyright (C) 2013 FIX94 + * + * 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 . + ****************************************************************************/ +#ifndef _MEM_MANAGER_HPP_ +#define _MEM_MANAGER_HPP_ + +#include +#include + +enum mem_states +{ + MEM_FREE = (1<<0), + ALLOC_USED = (1<<1), + ALLOC_END = (1<<2), + MEM_END = (1<<3), +}; + +class MemManager { +public: + MemManager(); + void Init(u8 *start, u8 *list, u32 size); + void ClearMem(); + void *Alloc(u32 size); + void Free(void *mem); + u32 MemBlockSize(void *mem); + u32 FreeSize(); + void *ReAlloc(void *mem, u32 size); +private: + u8 *startAddr; + u8 *memList; + u8 *memListEnd; + u32 memSize; +}; + +void MemMutexInit(); +void MemMutexDestroy(); + +#endif diff --git a/source/menu/menu.cpp b/source/menu/menu.cpp index 489aaeef..25fbf450 100644 --- a/source/menu/menu.cpp +++ b/source/menu/menu.cpp @@ -14,7 +14,7 @@ #include "channel/nand.hpp" #include "channel/nand_save.hpp" #include "gc/gc.hpp" -#include "gui/Gekko.h" +#include "hw/Gekko.h" #include "gui/GameTDB.hpp" #include "loader/alt_ios.h" #include "loader/cios.h" @@ -255,7 +255,7 @@ void CMenu::init() m_cfg.getBool(CHANNEL_DOMAIN, "disable", true); /* Load cIOS Map */ _installed_cios.clear(); - if(!neek2o()) + if(!neek2o() && !Sys_DolphinMode()) _load_installed_cioses(); else _installed_cios[CurrentIOS.Version] = CurrentIOS.Version; diff --git a/source/menu/menu_game.cpp b/source/menu/menu_game.cpp index fcadc98a..89214266 100644 --- a/source/menu/menu_game.cpp +++ b/source/menu/menu_game.cpp @@ -21,7 +21,6 @@ #include "gc/gcdisc.hpp" #include "gui/WiiMovie.hpp" #include "gui/GameTDB.hpp" -#include "gui/Gekko.h" #include "homebrew/homebrew.h" #include "loader/alt_ios.h" #include "loader/wdvd.h"