static inline bool do_check32 (size_t i, const Elf32_auxv_t (*a32)[], uint_fast8_t *elfdata) { /* The AUXV pointer might not even be naturally aligned for 32-bit data, because note payloads in a core file are not aligned. */ uint32_t type = read_4ubyte_unaligned_noncvt (&(*a32)[i].a_type); uint32_t val = read_4ubyte_unaligned_noncvt (&(*a32)[i].a_un.a_val); if (type == BE32 (PROBE_TYPE) && val == BE32 (PROBE_VAL32)) { *elfdata = ELFDATA2MSB; return true; } if (type == LE32 (PROBE_TYPE) && val == LE32 (PROBE_VAL32)) { *elfdata = ELFDATA2LSB; return true; } return false; }
UINT64_STRUCT GetHeaderField64 (byte *header, int offset) { UINT64_STRUCT uint64Struct; #ifndef TC_NO_COMPILER_INT64 uint64Struct.Value = BE64 (*(uint64 *) (header + offset)); #else uint64Struct.HighPart = BE32 (*(uint32 *) (header + offset)); uint64Struct.LowPart = BE32 (*(uint32 *) (header + offset + 4)); #endif return uint64Struct; }
static int process_read_file_cmd(client_t *client, netiso_read_file_cmd *cmd) { uint64_t offset; uint32_t remaining; int32_t bytes_read; netiso_read_file_result result; offset = BE64(cmd->offset); remaining = BE32(cmd->num_bytes); if (!client->ro_file) { bytes_read = -1; goto send_result; } if (remaining > BUFFER_SIZE) { bytes_read = -1; goto send_result; } if (client->ro_file->seek(offset, SEEK_SET) < 0) { bytes_read = -1; goto send_result; } bytes_read = client->ro_file->read(client->buf, remaining); if (bytes_read < 0) { bytes_read = -1; } send_result: result.bytes_read = (int32_t)BE32(bytes_read); if (send(client->s, (char *)&result, sizeof(result), 0) != 4) { DPRINTF("send failed on send result (read file)\n"); return -1; } if (bytes_read > 0 && send(client->s, (char *)client->buf, bytes_read, 0) != bytes_read) { DPRINTF("send failed on read file!\n"); return -1; } return 0; }
static int process_mkdir_cmd(client_t *client, netiso_mkdir_cmd *cmd) { netiso_mkdir_result result; char *dirpath; uint16_t dp_len; int ret; dp_len = BE16(cmd->dp_len); dirpath = (char *)malloc(dp_len+1); if (!dirpath) { DPRINTF("CRITICAL: memory allocation error\n"); return -1; } dirpath[dp_len] = 0; ret = recv_all(client->s, (void *)dirpath, dp_len); if (ret != dp_len) { DPRINTF("recv failed, getting dirname for mkdir: %d %d\n", ret, get_network_error()); free(dirpath); return -1; } dirpath = translate_path(dirpath, 1, 1, NULL); if (!dirpath) { DPRINTF("Path cannot be translated. Connection with this client will be aborted.\n"); return -1; } DPRINTF("mkdir %s\n", dirpath); #ifdef WIN32 result.mkdir_result = BE32(mkdir(dirpath)); #else result.mkdir_result = BE32(mkdir(dirpath, 0777)); #endif free(dirpath); ret = send(client->s, (char *)&result, sizeof(result), 0); if (ret != sizeof(result)) { DPRINTF("open dir, send result error: %d %d\n", ret, get_network_error()); return -1; } return 0; }
static int process_write_file_cmd(client_t *client, netiso_write_file_cmd *cmd) { uint32_t remaining; int32_t bytes_written; netiso_write_file_result result; remaining = BE32(cmd->num_bytes); if (!client->wo_file) { bytes_written = -1; goto send_result; } if (remaining > BUFFER_SIZE) { return -1; } //DPRINTF("Remaining: %d\n", remaining); if (remaining > 0) { int ret = recv_all(client->s, (void *)client->buf, remaining); if (ret != remaining) { DPRINTF("recv failed on write file: %d %d\n", ret, get_network_error()); return -1; } } bytes_written = client->wo_file->write(client->buf, remaining); if (bytes_written < 0) { bytes_written = -1; } send_result: result.bytes_written = (int32_t)BE32(bytes_written); if (send(client->s, (char *)&result, sizeof(result), 0) != 4) { DPRINTF("send failed on send result (read file)\n"); return -1; } return 0; }
int dme_read_unit_desc(struct ufs_dev *dev, uint8_t index) { STACKBUF_DMA_ALIGN(unit_desc, sizeof(struct ufs_unit_desc)); struct ufs_unit_desc *desc = (struct ufs_unit_desc *) unit_desc; struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR, UFS_DESC_IDN_UNIT, index, 0, (addr_t) unit_desc, sizeof(struct ufs_unit_desc)}; if (dme_send_query_upiu(dev, &query)) { dprintf(CRITICAL, "%s:%d DME Read Unit Descriptor request failed\n", __func__, __LINE__); return -UFS_FAILURE; } /* Flush buffer. */ arch_invalidate_cache_range((addr_t) desc, sizeof(struct ufs_unit_desc)); dev->lun_cfg[index].logical_blk_cnt = BE64(desc->logical_blk_cnt); dev->lun_cfg[index].erase_blk_size = BE32(desc->erase_blk_size); // use only the lower 32 bits for rpmb partition size if (index == UFS_WLUN_RPMB) dev->rpmb_num_blocks = BE32(desc->logical_blk_cnt >> 32); return UFS_SUCCESS; }
/** * parse_vblk - parse a LDM database vblk record * @buffer: vblk record loaded from the LDM database * @buf_size: size of @buffer in bytes * @vb: in memory vblk structure to return parsed information in * * This parses the LDM database vblk record supplied in @buffer and sets up * the in memory vblk structure @vb with the obtained information. * * Return 1 on success, 0 if successful but record not in use, and -1 on error. * If the return value is 0 or -1, @vb is undefined. * * NOTE: Currently the only record type we handle is VBLK_PART, i.e. records * describing a partition. For all others, we just set @vb->vblk_type to 0 and * return success. This of course means that if @vb->vblk_type is zero, all * other fields in @vb are undefined. */ static int parse_vblk(const u8 *buffer, const int buf_size, struct vblk *vb) { int err = 1; if (buf_size < 0x14) return -1; if (MAGIC_VBLK != BE32(buffer)) { printk(LDM_CRIT "Cannot find VBLK, database may be corrupt.\n"); return -1; } if ((BE16(buffer + 0x0E) == 0) || /* Record is not in use. */ (BE16(buffer + 0x0C) != 0)) /* Part 2 of an ext. record */ return 0; /* FIXME: What about extended VBLKs? */ switch (buffer[0x13]) { case VBLK_PART: err = parse_vblk_part(buffer, buf_size, vb); break; default: vb->vblk_type = 0; } if (err != -1) ldm_debug("Parsed VBLK successfully.\n"); return err; }
inline bool check32 (size_t i) { if (u->a32[i].a_type == BE32 (PROBE_TYPE) && u->a32[i].a_un.a_val == BE32 (PROBE_VAL32)) { *elfdata = ELFDATA2MSB; return true; } if (u->a32[i].a_type == LE32 (PROBE_TYPE) && u->a32[i].a_un.a_val == LE32 (PROBE_VAL32)) { *elfdata = ELFDATA2LSB; return true; } return false; }
static int process_read_cd_2048_critical_cmd(client_t *client, netiso_read_cd_2048_critical_cmd *cmd) { uint64_t offset; uint32_t sector_count; uint8_t *buf; offset = BE32(cmd->start_sector)*2352; sector_count = BE32(cmd->sector_count); DPRINTF("Read CD 2048 %x %x\n", BE32(cmd->start_sector), sector_count); if (!client->ro_file) return -1; if ((sector_count*2048) > BUFFER_SIZE) { // This is just to save some uneeded code. PS3 will never request such a high number of sectors DPRINTF("This situation wasn't expected, too many sectors read!\n"); return -1; } buf = client->buf; for (uint32_t i = 0; i < sector_count; i++) { client->ro_file->seek(offset+24, SEEK_SET); if (client->ro_file->read(buf, 2048) != 2048) { DPRINTF("read_file failed on read cd 2048 critical command!\n"); return -1; } buf += 2048; offset += 2352; } if (send(client->s, (char *)client->buf, sector_count*2048, 0) != (sector_count*2048)) { DPRINTF("send failed on read cd 2048 critical command!\n"); return -1; } return 0; }
/* * Initializes an RPC request header as needed for KMS, i.e. packet always fits in one fragment. * size cannot be greater than fragment length negotiated during RPC bind. */ static void createRpcHeader(RPC_HEADER* header, BYTE packetType, WORD size) { header->PacketType = packetType; header->PacketFlags = RPC_PF_FIRST | RPC_PF_LAST; header->VersionMajor = 5; header->VersionMinor = 0; header->AuthLength = 0; header->DataRepresentation = BE32(0x10000000); // Little endian, ASCII charset, IEEE floating point header->CallId = LE32(CallId); header->FragLength = LE16(size); }
inline void GCMemcardDirectory::SyncSaves() { Directory *current = &m_dir2; if (BE16(m_dir1.UpdateCounter) > BE16(m_dir2.UpdateCounter)) { current = &m_dir1; } for (u32 i = 0; i < DIRLEN; ++i) { if (BE32(current->Dir[i].Gamecode) != 0xFFFFFFFF) { INFO_LOG(EXPANSIONINTERFACE, "Syncing Save %x", *(u32 *)&(current->Dir[i].Gamecode)); bool added = false; while (i >= m_saves.size()) { GCIFile temp; m_saves.push_back(temp); added = true; } if (added || memcmp((u8 *)&(m_saves[i].m_gci_header), (u8 *)&(current->Dir[i]), DENTRY_SIZE)) { m_saves[i].m_dirty = true; u32 gamecode = BE32(m_saves[i].m_gci_header.Gamecode); u32 newGameCode = BE32(current->Dir[i].Gamecode); u32 old_start = BE16(m_saves[i].m_gci_header.FirstBlock); u32 new_start = BE16(current->Dir[i].FirstBlock); if ((gamecode != 0xFFFFFFFF) && (gamecode != newGameCode)) { PanicAlertT("Game overwrote with another games save, data corruption ahead %x, %x ", BE32(m_saves[i].m_gci_header.Gamecode), BE32(current->Dir[i].Gamecode)); } memcpy((u8 *)&(m_saves[i].m_gci_header), (u8 *)&(current->Dir[i]), DENTRY_SIZE); if (old_start != new_start) { INFO_LOG(EXPANSIONINTERFACE, "Save moved from %x to %x", old_start, new_start); m_saves[i].m_used_blocks.clear(); m_saves[i].m_save_data.clear(); } if (m_saves[i].m_used_blocks.size() == 0) { SetUsedBlocks(i); } } } else if ((i < m_saves.size()) && (*(u32 *)&(m_saves[i].m_gci_header) != 0xFFFFFFFF)) { INFO_LOG(EXPANSIONINTERFACE, "Clearing and/or Deleting Save %x", BE32(m_saves[i].m_gci_header.Gamecode)); *(u32 *)&(m_saves[i].m_gci_header.Gamecode) = 0xFFFFFFFF; m_saves[i].m_save_data.clear(); m_saves[i].m_used_blocks.clear(); m_saves[i].m_dirty = true; } } }
static int process_read_file_critical(client_t *client, netiso_read_file_critical_cmd *cmd) { uint64_t offset; uint32_t remaining; offset = BE64(cmd->offset); remaining = BE32(cmd->num_bytes); if (!client->ro_file) return -1; #ifdef WIN32 DPRINTF("Read %I64x %x\n", (long long unsigned int)offset, remaining); #else DPRINTF("Read %llx %x\n", (long long unsigned int)offset, remaining); #endif if (client->ro_file->seek(offset, SEEK_SET) < 0) { DPRINTF("seek_file failed!\n"); return -1; } while (remaining > 0) { uint32_t read_size; if (remaining < BUFFER_SIZE) { read_size = remaining; } else { read_size = BUFFER_SIZE; } if (client->ro_file->read(client->buf, read_size) != read_size) { DPRINTF("read_file failed on read file critical command!\n"); return -1; } if (send(client->s, (char *)client->buf, read_size, 0) != read_size) { DPRINTF("send failed on read file critical command!\n"); return -1; } remaining -= read_size; } return 0; }
void VIsoFile::fixPathTableLba(uint8_t *pathTable, size_t size, uint32_t dirLba, bool msb) { uint8_t *p = pathTable; while ((p < (pathTable+size))) { Iso9660PathTable *table = (Iso9660PathTable *)p; if (msb) { table->dirLocation = BE32(BE32(table->dirLocation)+dirLba); } else { table->dirLocation = LE32(LE32(table->dirLocation)+dirLba); } p = p+8+table->len_di; if (table->len_di&1) p++; } }
int ucs_do_scsi_unmap(struct ufs_dev *dev, struct scsi_unmap_req *req) { STACKBUF_DMA_ALIGN(cdb_param, SCSI_CDB_PARAM_LEN); STACKBUF_DMA_ALIGN(param, sizeof(struct unmap_param_list)); struct scsi_req_build_type req_upiu; struct unmap_param_list *param_list; struct unmap_blk_desc *blk_desc; param_list = (struct unmap_param_list *)param; param_list->data_len = (sizeof(struct unmap_param_list) - 1) << 0x8; /* n-1 */ param_list->blk_desc_data_len = sizeof(struct unmap_blk_desc) << 0x8; blk_desc = &(param_list->blk_desc); blk_desc->lba = BE64(req->start_lba); blk_desc->num_blks = BE32(req->num_blocks); memset((void*)cdb_param, 0, SCSI_CDB_PARAM_LEN); cdb_param[0] = SCSI_CMD_UNMAP; cdb_param[1] = 0; /*ANCHOR = 0 for UFS*/ cdb_param[6] = 0; /*Group No = 0*/ cdb_param[7] = 0; /* Param list length is 1, we erase 1 contiguous blk*/ cdb_param[8] = sizeof(struct unmap_param_list); cdb_param[9] = 0; /* Flush cdb to memory. */ dsb(); arch_invalidate_cache_range((addr_t) cdb_param, SCSI_CDB_PARAM_LEN); memset((void*)&req_upiu, 0 , sizeof(struct scsi_req_build_type)); req_upiu.cdb = (addr_t) cdb_param; req_upiu.data_buffer_addr = (addr_t) param; req_upiu.data_len = sizeof(struct unmap_param_list); req_upiu.flags = UPIU_FLAGS_WRITE; req_upiu.lun = req->lun; req_upiu.dd = UTRD_SYSTEM_TO_TARGET; if (ucs_do_scsi_cmd(dev, &req_upiu)) { dprintf(CRITICAL, "Failed to send SCSI unmap command \n"); return -UFS_FAILURE; } /* Flush buffer. */ arch_invalidate_cache_range((addr_t) param, SCSI_INQUIRY_LEN); return UFS_SUCCESS; }
void VIsoFile::fixDirLba(Iso9660DirectoryRecord *record, size_t size, uint32_t dirLba, uint32_t filesLba) { uint8_t *p, *buf; uint32_t pos = 0; buf = p = (uint8_t *)record; while ((p < (buf+size))) { Iso9660DirectoryRecord *current = (Iso9660DirectoryRecord *)p; if (current->len_dr == 0) { p += (0x800 - (pos&0x7ff)); pos += (0x800 - (pos&0x7ff)); if (p >= (buf+size)) break; current = (Iso9660DirectoryRecord *)p; if (current->len_dr == 0) break; } if (current->fileFlags & ISO_DIRECTORY) { current->lsbStart = LE32(LE32(current->lsbStart)+dirLba); current->msbStart = BE32(BE32(current->msbStart)+dirLba); } else { current->lsbStart = LE32(LE32(current->lsbStart)+filesLba); current->msbStart = BE32(BE32(current->msbStart)+filesLba); } p += current->len_dr; pos += current->len_dr; } }
void* mio0decode(void * source, int * ret_size){ unsigned int target_size = BE32(source+0x04); void * dest = malloc(target_size); *ret_size = target_size; void * destination = dest; void * destination_end = destination + target_size; void * offset1 = source + BE32(source+0x08); void * offset2 = source + BE32(source+0x0C); void * offset0 = source + 0x10; unsigned short t2_s = 0; char t2_c = 0; unsigned char t3 = 0; void * t1; int t0 = 0; char a2 = 0; while(destination < destination_end){ if(a2 == 0){ t0 = BE32(offset0); a2 = 32; offset0 += sizeof(int); } if(t0 >= 0x00000000){ t2_s = BE16(offset1); offset1 += sizeof(unsigned short); t3 = t2_s >> 12; t2_s &= 0x0FFF; t1 = destination - t2_s; t3 += 3; while(t3 != 0){ t2_c = *(char*)(t1 - 1); t3--; t1++; *(char*)(destination) = t2_c; destination++; } } else {
/* * Checks RPC header. Returns 0 on success. * This is mainly for debugging a non Microsoft KMS server that uses its own RPC code. */ static int checkRpcHeader(const RPC_HEADER *const header, const BYTE desiredPacketType, const PRINTFUNC p) { int status = 0; if (header->PacketType != desiredPacketType) { p("Fatal: Received wrong RPC packet type. Expected %u but got %u\n", (uint32_t)desiredPacketType, header->PacketType ); status = RPC_S_PROTOCOL_ERROR; } if (header->DataRepresentation != BE32(0x10000000)) { p("Fatal: RPC response does not conform to Microsoft's limited support of DCE RPC\n"); status = RPC_S_PROTOCOL_ERROR; } if (header->AuthLength != 0) { p("Fatal: RPC response requests authentication\n"); status = RPC_S_UNKNOWN_AUTHN_TYPE; } // vlmcsd does not support fragmented packets (not yet neccassary) if ((header->PacketFlags & (RPC_PF_FIRST | RPC_PF_LAST)) != (RPC_PF_FIRST | RPC_PF_LAST)) { p("Fatal: RPC packet flags RPC_PF_FIRST and RPC_PF_LAST are not both set.\n"); status = RPC_S_CANNOT_SUPPORT; } if (header->PacketFlags & RPC_PF_CANCEL_PENDING) p("Warning: %s should not be set\n", "RPC_PF_CANCEL_PENDING"); if (header->PacketFlags & RPC_PF_RESERVED) p("Warning: %s should not be set\n", "RPC_PF_RESERVED"); if (header->PacketFlags & RPC_PF_NOT_EXEC) p("Warning: %s should not be set\n", "RPC_PF_NOT_EXEC"); if (header->PacketFlags & RPC_PF_MAYBE) p("Warning: %s should not be set\n", "RPC_PF_MAYBE"); if (header->PacketFlags & RPC_PF_OBJECT) p("Warning: %s should not be set\n", "RPC_PF_OBJECT"); if (header->VersionMajor != 5 || header->VersionMinor != 0) { p("Fatal: Expected RPC version 5.0 and got %u.%u\n", header->VersionMajor, header->VersionMinor); status = RPC_S_INVALID_VERS_OPTION; } return status; }
static int process_delete_file_cmd(client_t *client, netiso_delete_file_cmd *cmd) { netiso_delete_file_result result; char *filepath; uint16_t fp_len; int ret; fp_len = BE16(cmd->fp_len); filepath = (char *)malloc(fp_len+1); if (!filepath) { DPRINTF("CRITICAL: memory allocation error\n"); return -1; } filepath[fp_len] = 0; ret = recv_all(client->s, (void *)filepath, fp_len); if (ret != fp_len) { DPRINTF("recv failed, getting filename for delete file: %d %d\n", ret, get_network_error()); free(filepath); return -1; } filepath = translate_path(filepath, 1, 1, NULL); if (!filepath) { DPRINTF("Path cannot be translated. Connection with this client will be aborted.\n"); return -1; } DPRINTF("delete %s\n", filepath); result.delete_result = BE32(unlink(filepath)); free(filepath); ret = send(client->s, (char *)&result, sizeof(result), 0); if (ret != sizeof(result)) { DPRINTF("delete, send result error: %d %d\n", ret, get_network_error()); return -1; } return 0; }
static void Sha256ProcessBlock(Sha256Ctx *Ctx, BYTE *block) { unsigned int i; DWORD w[64], temp1, temp2; DWORD a = Ctx->State[0]; DWORD b = Ctx->State[1]; DWORD c = Ctx->State[2]; DWORD d = Ctx->State[3]; DWORD e = Ctx->State[4]; DWORD f = Ctx->State[5]; DWORD g = Ctx->State[6]; DWORD h = Ctx->State[7]; for (i = 0; i < 16; i++) //w[ i ] = GET_UAA32BE(block, i); w[i] = BE32(((DWORD*)block)[i]); for (i = 16; i < 64; i++) w[ i ] = SI4(w[ i - 2 ]) + w[ i - 7 ] + SI3(w[ i - 15 ]) + w[ i - 16 ]; for (i = 0; i < 64; i++) { temp1 = h + SI2(e) + F0(e, f, g) + k[ i ] + w[ i ]; temp2 = SI1(a) + F1(a, b, c); h = g; g = f; f = e; e = d + temp1; d = c; c = b; b = a; a = temp1 + temp2; } Ctx->State[0] += a; Ctx->State[1] += b; Ctx->State[2] += c; Ctx->State[3] += d; Ctx->State[4] += e; Ctx->State[5] += f; Ctx->State[6] += g; Ctx->State[7] += h; }
Option<uint32_t> RawContainer::readUInt32(const IO::Stream::Ptr &f) { if (m_endian == ENDIAN_NULL) { LOGERR("null endian\n"); return Option<uint32_t>(); } unsigned char buf[4]; int s = f->read(buf, 4); if (s != 4) { return Option<uint32_t>(); } if (m_endian == ENDIAN_LITTLE) { return Option<uint32_t>(EL32(buf)); } else { return Option<uint32_t>(BE32(buf)); } }
void sha512_pkcs5_2( int i_count, const void *pwd, size_t pwd_len, const char *salt, size_t salt_len, char *dk, size_t dklen ) { u8 buff[128]; u8 blk[SHA512_DIGEST_SIZE]; u8 hmac[SHA512_DIGEST_SIZE]; u32 block = 1; size_t c_len, j; int i; while (dklen != 0) { /* first interation */ mincpy(buff, salt, salt_len); p32(buff + salt_len)[0] = BE32(block); sha512_hmac(pwd, pwd_len, buff, salt_len + 4, hmac); autocpy(blk, hmac, SHA512_DIGEST_SIZE); /* next interations */ for (i = 1; i < i_count; i++) { sha512_hmac(pwd, pwd_len, hmac, SHA512_DIGEST_SIZE, hmac); for (j = 0; j < SHA512_DIGEST_SIZE; j++) { blk[j] ^= hmac[j]; } } c_len = min(dklen, SHA512_DIGEST_SIZE); mincpy(dk, blk, c_len); dk += c_len; dklen -= c_len; block++; } /* prevent leaks */ zeroauto(buff, sizeof(buff)); zeroauto(blk, sizeof(blk)); zeroauto(hmac, sizeof(hmac)); }
static void Sha256Finish(Sha256Ctx *Ctx, BYTE *hash) { unsigned int i, b_len = Ctx->Len & 63; Ctx->Buffer[ b_len ] = 0x80; if ( b_len ^ 63 ) memset(Ctx->Buffer + b_len + 1, 0, b_len ^ 63); if ( b_len >= 56 ) { Sha256ProcessBlock(Ctx, Ctx->Buffer); memset(Ctx->Buffer, 0, 56); } //PUT_UAA64BE(Ctx->Buffer, (unsigned long long)(Ctx->Len * 8), 7); ((uint64_t*)Ctx->Buffer)[7] = BE64((uint64_t)Ctx->Len << 3); Sha256ProcessBlock(Ctx, Ctx->Buffer); for (i = 0; i < 8; i++) //PUT_UAA32BE(hash, Ctx->State[i], i); ((DWORD*)hash)[i] = BE32(Ctx->State[i]); }
inline s32 GCMemcardDirectory::SaveAreaRW(u32 block, bool writing) { for (u16 i = 0; i < m_saves.size(); ++i) { if (BE32(m_saves[i].m_gci_header.Gamecode) != 0xFFFFFFFF) { if (m_saves[i].m_used_blocks.size() == 0) { SetUsedBlocks(i); } int idx = m_saves[i].UsesBlock(block); if (idx != -1) { if (!m_saves[i].LoadSaveBlocks()) { int num_blocks = BE16(m_saves[i].m_gci_header.BlockCount); while (num_blocks) { m_saves[i].m_save_data.emplace_back(); num_blocks--; } } if (writing) { m_saves[i].m_dirty = true; } m_LastBlock = block; m_LastBlockAddress = m_saves[i].m_save_data[idx].block; return m_LastBlock; } } } return -1; }
/* Examine an auxv data block and determine its format. Return true iff we figured it out. */ static bool auxv_format_probe (const void *auxv, size_t size, uint_fast8_t *elfclass, uint_fast8_t *elfdata) { const union { char buf[size]; Elf32_auxv_t a32[size / sizeof (Elf32_auxv_t)]; Elf64_auxv_t a64[size / sizeof (Elf64_auxv_t)]; } *u = auxv; inline bool check64 (size_t i) { if (u->a64[i].a_type == BE64 (PROBE_TYPE) && u->a64[i].a_un.a_val == BE64 (PROBE_VAL64)) { *elfdata = ELFDATA2MSB; return true; } if (u->a64[i].a_type == LE64 (PROBE_TYPE) && u->a64[i].a_un.a_val == LE64 (PROBE_VAL64)) { *elfdata = ELFDATA2LSB; return true; } return false; } inline bool check32 (size_t i) { if (u->a32[i].a_type == BE32 (PROBE_TYPE) && u->a32[i].a_un.a_val == BE32 (PROBE_VAL32)) { *elfdata = ELFDATA2MSB; return true; } if (u->a32[i].a_type == LE32 (PROBE_TYPE) && u->a32[i].a_un.a_val == LE32 (PROBE_VAL32)) { *elfdata = ELFDATA2LSB; return true; } return false; } for (size_t i = 0; i < size / sizeof (Elf64_auxv_t); ++i) { if (check64 (i)) { *elfclass = ELFCLASS64; return true; } if (check32 (i * 2) || check32 (i * 2 + 1)) { *elfclass = ELFCLASS32; return true; } } return false; }
static int report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata, Dwfl *dwfl, GElf_Addr r_debug_vaddr, Dwfl_Memory_Callback *memory_callback, void *memory_callback_arg) { /* Skip r_version, to aligned r_map field. */ GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass); void *buffer = NULL; size_t buffer_available = 0; inline int release_buffer (int result) { if (buffer != NULL) (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0, memory_callback_arg); return result; } GElf_Addr addrs[4]; inline bool read_addrs (GElf_Addr vaddr, size_t n) { size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read. */ /* Read a new buffer if the old one doesn't cover these words. */ if (buffer == NULL || vaddr < read_vaddr || vaddr - read_vaddr + nb > buffer_available) { release_buffer (0); read_vaddr = vaddr; int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL); if (unlikely (segndx < 0) || unlikely (! (*memory_callback) (dwfl, segndx, &buffer, &buffer_available, vaddr, nb, memory_callback_arg))) return true; } const union { Elf32_Addr a32[n]; Elf64_Addr a64[n]; } *in = vaddr - read_vaddr + buffer; if (elfclass == ELFCLASS32) { if (elfdata == ELFDATA2MSB) for (size_t i = 0; i < n; ++i) addrs[i] = BE32 (in->a32[i]); else for (size_t i = 0; i < n; ++i) addrs[i] = LE32 (in->a32[i]); } else { if (elfdata == ELFDATA2MSB) for (size_t i = 0; i < n; ++i) addrs[i] = BE64 (in->a64[i]); else for (size_t i = 0; i < n; ++i) addrs[i] = LE64 (in->a64[i]); } return false; }
static int process_open_dir_cmd(client_t *client, netiso_open_dir_cmd *cmd) { netiso_open_dir_result result; char *dirpath; uint16_t dp_len; int ret; dp_len = BE16(cmd->dp_len); //DPRINTF("fp_len = %d\n", fp_len); dirpath = (char *)malloc(dp_len+1); if (!dirpath) { DPRINTF("CRITICAL: memory allocation error\n"); return -1; } dirpath[dp_len] = 0; ret = recv_all(client->s, (void *)dirpath, dp_len); if (ret != dp_len) { DPRINTF("recv failed, getting dirname for open dir: %d %d\n", ret, get_network_error()); free(dirpath); return -1; } dirpath = translate_path(dirpath, 1, 1, NULL); if (!dirpath) { DPRINTF("Path cannot be translated. Connection with this client will be aborted.\n"); return -1; } DPRINTF("open dir %s\n", dirpath); if (client->dir) { closedir(client->dir); client->dir = NULL; } if (client->dirpath) { free(client->dirpath); } client->dirpath = NULL; client->dir = opendir(dirpath); if (!client->dir) { DPRINTF("open dir error on \"%s\"\n", dirpath); result.open_result = BE32(-1); } else { client->dirpath = dirpath; result.open_result = BE32(0); } if (!client->dirpath) free(dirpath); ret = send(client->s, (char *)&result, sizeof(result), 0); if (ret != sizeof(result)) { DPRINTF("open dir, send result error: %d %d\n", ret, get_network_error()); return -1; } return 0; }
static int process_create_cmd(client_t *client, netiso_create_cmd *cmd) { netiso_create_result result; char *filepath; uint16_t fp_len; int ret; fp_len = BE16(cmd->fp_len); //DPRINTF("fp_len = %d\n", fp_len); filepath = (char *)malloc(fp_len+1); if (!filepath) { DPRINTF("CRITICAL: memory allocation error\n"); return -1; } filepath[fp_len] = 0; ret = recv_all(client->s, (void *)filepath, fp_len); if (ret != fp_len) { DPRINTF("recv failed, getting filename for create: %d %d\n", ret, get_network_error()); free(filepath); return -1; } filepath = translate_path(filepath, 1, 1, NULL); if (!filepath) { DPRINTF("Path cannot be translated. Connection with this client will be aborted.\n"); return -1; } DPRINTF("create %s\n", filepath); if (client->wo_file) { delete client->wo_file; } client->wo_file = new File(); if (client->wo_file->open(filepath, O_WRONLY|O_CREAT|O_TRUNC) < 0) { DPRINTF("create error on \"%s\"\n", filepath); result.create_result = BE32(-1); delete client->wo_file; client->wo_file = NULL; } else { result.create_result = BE32(0); } free(filepath); ret = send(client->s, (char *)&result, sizeof(result), 0); if (ret != sizeof(result)) { DPRINTF("create, send result error: %d %d\n", ret, get_network_error()); return -1; } return 0; }
int main(int argc, char *argv[]) { int s; uint32_t whitelist_start = 0; uint32_t whitelist_end = 0; uint16_t port = NETISO_PORT; #ifndef WIN32 if (sizeof(off_t) < 8) { DPRINTF("off_t too small!\n"); return -1; } #endif if (argc < 2) { printf("Usage: %s rootdirectory [port] [whitelist]\nDefault port: %d\nWhitelist: x.x.x.x, where x is 0-255 or * (e.g 192.168.1.* to allow only connections from 192.168.1.0-192.168.1.255)\n", argv[0], NETISO_PORT); return -1; } if (strlen(argv[1]) >= sizeof(root_directory)) { printf("Directory name too long!\n"); return -1; } strcpy(root_directory, argv[1]); for (int i = strlen(root_directory)-1; i>= 0; i--) { if (root_directory[i] == '/' || root_directory[i] == '\\') root_directory[i] = 0; else break; } if (strlen(root_directory) == 0) { printf("/ can't be specified as root directory!\n"); return -1; } if (argc > 2) { uint32_t u; if (sscanf(argv[2], "%u", &u) != 1) { printf("Wrong port specified.\n"); return -1; } #ifdef WIN32 uint32_t min = 1; #else uint32_t min = 1024; #endif if (u < min || u > 65535) { printf("Port must be in %d-65535 range.\n", min); return -1; } port = u; } if (argc > 3) { char *p = argv[3]; for (int i = 3; i >= 0; i--) { uint32_t u; int wildcard = 0; if (sscanf(p, "%u", &u) != 1) { if (i == 0) { if (strcmp(p, "*") != 0) { printf("Wrong whitelist format.\n"); return -1; } } else { if (p[0] != '*' || p[1] != '.') { printf("Wrong whitelist format.\n"); return -1; } } wildcard = 1; } else { if (u > 0xFF) { printf("Wrong whitelist format.\n"); return -1; } } if (wildcard) { whitelist_end |= (0xFF<<(i*8)); } else { whitelist_start |= (u<<(i*8)); whitelist_end |= (u<<(i*8)); } if (i != 0) { p = strchr(p, '.'); if (!p) { printf("Wrong whitelist format.\n"); return -1; } p++; } } DPRINTF("Whitelist: %08X-%08X\n", whitelist_start, whitelist_end); } s = initialize_socket(port); if (s < 0) { printf("Error in initialization.\n"); return -1; } memset(clients, 0, sizeof(clients)); printf("Waiting for client...\n"); for (;;) { struct sockaddr_in addr; unsigned int size; int cs; int i; size = sizeof(addr); cs = accept(s, (struct sockaddr *)&addr, (socklen_t *)&size); if (cs < 0) { DPRINTF("Accept error: %d\n", get_network_error()); printf("Network error.\n"); break; } // Check for same client for (i = 0; i < MAX_CLIENTS; i++) { if (clients[i].connected && clients[i].ip_addr.s_addr == addr.sin_addr.s_addr) break; } if (i != MAX_CLIENTS) { // Shutdown socket and wait for thread to complete shutdown(clients[i].s, SHUT_RDWR); closesocket(clients[i].s); join_thread(clients[i].thread); printf("Reconnection from %s\n", inet_ntoa(addr.sin_addr)); } else { if (whitelist_start != 0) { uint32_t ip = BE32(addr.sin_addr.s_addr); if (ip < whitelist_start || ip > whitelist_end) { printf("Rejected connection from %s (not in whitelist)\n", inet_ntoa(addr.sin_addr)); closesocket(cs); continue; } } for (i = 0; i < MAX_CLIENTS; i++) { if (!clients[i].connected) break; } if (i == MAX_CLIENTS) { printf("Too many connections! (rejected client: %s)\n", inet_ntoa(addr.sin_addr)); closesocket(cs); continue; } printf("Connection from %s\n", inet_ntoa(addr.sin_addr)); } if (initialize_client(&clients[i]) != 0) { printf("System seems low in resources.\n"); break; } clients[i].s = cs; clients[i].ip_addr = addr.sin_addr; create_start_thread(&clients[i].thread, client_thread, &clients[i]); } #ifdef WIN32 WSACleanup(); #endif return 0; }
void GCMemcardDirectory::FlushToFile() { std::unique_lock<std::mutex> l(m_write_mutex); int errors = 0; DEntry invalid; for (u16 i = 0; i < m_saves.size(); ++i) { if (m_saves[i].m_dirty) { if (BE32(m_saves[i].m_gci_header.Gamecode) != 0xFFFFFFFF) { m_saves[i].m_dirty = false; if (m_saves[i].m_filename.empty()) { std::string defaultSaveName = m_SaveDirectory + m_saves[i].m_gci_header.GCI_FileName(); // Check to see if another file is using the same name // This seems unlikely except in the case of file corruption // otherwise what user would name another file this way? for (int j = 0; File::Exists(defaultSaveName) && j < 10; ++j) { defaultSaveName.insert(defaultSaveName.end() - 4, '0'); } if (File::Exists(defaultSaveName)) PanicAlertT("Failed to find new filename\n %s\n will be overwritten", defaultSaveName.c_str()); m_saves[i].m_filename = defaultSaveName; } File::IOFile GCI(m_saves[i].m_filename, "wb"); if (GCI) { GCI.WriteBytes(&m_saves[i].m_gci_header, DENTRY_SIZE); GCI.WriteBytes(m_saves[i].m_save_data.data(), BLOCK_SIZE * m_saves[i].m_save_data.size()); if (GCI.IsGood()) { Core::DisplayMessage( StringFromFormat("Wrote save contents to %s", m_saves[i].m_filename.c_str()), 4000); } else { ++errors; Core::DisplayMessage( StringFromFormat("Failed to write save contents to %s", m_saves[i].m_filename.c_str()), 4000); ERROR_LOG(EXPANSIONINTERFACE, "Failed to save data to %s", m_saves[i].m_filename.c_str()); } } } else if (m_saves[i].m_filename.length() != 0) { m_saves[i].m_dirty = false; std::string &oldname = m_saves[i].m_filename; std::string deletedname = oldname + ".deleted"; if (File::Exists(deletedname)) File::Delete(deletedname); File::Rename(oldname, deletedname); m_saves[i].m_filename.clear(); m_saves[i].m_save_data.clear(); m_saves[i].m_used_blocks.clear(); } } // Unload the save data for any game that is not running // we could use !m_dirty, but some games have multiple gci files and may not write to them simultaneously // this ensures that the save data for all of the current games gci files are stored in the savestate u32 gamecode = BE32(m_saves[i].m_gci_header.Gamecode); if (gamecode != m_GameId && gamecode != 0xFFFFFFFF && m_saves[i].m_save_data.size()) { INFO_LOG(EXPANSIONINTERFACE, "Flushing savedata to disk for %s", m_saves[i].m_filename.c_str()); m_saves[i].m_save_data.clear(); } } #if _WRITE_MC_HEADER u8 mc[BLOCK_SIZE * MC_FST_BLOCKS]; Read(0, BLOCK_SIZE * MC_FST_BLOCKS, mc); File::IOFile hdrfile(m_SaveDirectory + MC_HDR, "wb"); hdrfile.WriteBytes(mc, BLOCK_SIZE * MC_FST_BLOCKS); #endif }
int GCMemcardDirectory::LoadGCI(const std::string& fileName, DiscIO::IVolume::ECountry card_region, bool currentGameOnly) { File::IOFile gcifile(fileName, "rb"); if (gcifile) { GCIFile gci; gci.m_filename = fileName; gci.m_dirty = false; if (!gcifile.ReadBytes(&(gci.m_gci_header), DENTRY_SIZE)) { ERROR_LOG(EXPANSIONINTERFACE, "%s failed to read header", fileName.c_str()); return NO_INDEX; } DiscIO::IVolume::ECountry gci_region; // check region switch (gci.m_gci_header.Gamecode[3]) { case 'J': gci_region = DiscIO::IVolume::COUNTRY_JAPAN; break; case 'E': gci_region = DiscIO::IVolume::COUNTRY_USA; break; case 'C': // Used by Datel Action Replay Save // can be on any regions card gci_region = card_region; break; default: gci_region = DiscIO::IVolume::COUNTRY_EUROPE; break; } if (gci_region != card_region) { PanicAlertT("GCI save file was not loaded because it is the wrong region for this memory card:\n%s", fileName.c_str()); return NO_INDEX; } std::string gci_filename = gci.m_gci_header.GCI_FileName(); for (u16 i = 0; i < m_loaded_saves.size(); ++i) { if (m_loaded_saves[i] == gci_filename) { PanicAlertT( "%s\nwas not loaded because it has the same internal filename as previously loaded save\n%s", gci.m_filename.c_str(), m_saves[i].m_filename.c_str()); return NO_INDEX; } } u16 numBlocks = BE16(gci.m_gci_header.BlockCount); // largest number of free blocks on a memory card // in reality, there are not likely any valid gci files > 251 blocks if (numBlocks > 2043) { PanicAlertT("%s\nwas not loaded because it is an invalid gci.\n Number of blocks claimed to be %d", gci.m_filename.c_str(), numBlocks); return NO_INDEX; } u32 size = numBlocks * BLOCK_SIZE; u64 file_size = gcifile.GetSize(); if (file_size != size + DENTRY_SIZE) { PanicAlertT("%s\nwas not loaded because it is an invalid gci.\n File size (%" PRIx64 ") does not match the size recorded in the header (%d)", gci.m_filename.c_str(), file_size, size + DENTRY_SIZE); return NO_INDEX; } if (m_GameId == BE32(gci.m_gci_header.Gamecode)) { gci.LoadSaveBlocks(); } else { if (currentGameOnly) { return NO_INDEX; } int totalBlocks = BE16(m_hdr.SizeMb)*MBIT_TO_BLOCKS - MC_FST_BLOCKS; int freeBlocks = BE16(m_bat1.FreeBlocks); if (totalBlocks > freeBlocks * 10) { PanicAlertT("%s\nwas not loaded because there is less than 10%% free space on the memorycard\n"\ "Total Blocks: %d; Free Blocks: %d", gci.m_filename.c_str(), totalBlocks, freeBlocks); return NO_INDEX; } } u16 first_block = m_bat1.AssignBlocksContiguous(numBlocks); if (first_block == 0xFFFF) { PanicAlertT("%s\nwas not loaded because there are not enough free blocks on virtual memorycard", fileName.c_str()); return NO_INDEX; } *(u16 *)&gci.m_gci_header.FirstBlock = first_block; if (gci.HasCopyProtection() && gci.LoadSaveBlocks()) { GCMemcard::PSO_MakeSaveGameValid(m_hdr, gci.m_gci_header, gci.m_save_data); GCMemcard::FZEROGX_MakeSaveGameValid(m_hdr, gci.m_gci_header, gci.m_save_data); } int idx = (int)m_saves.size(); m_dir1.Replace(gci.m_gci_header, idx); m_saves.push_back(std::move(gci)); SetUsedBlocks(idx); return idx; } return NO_INDEX; }