1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include "ErrorLog.h" 19 #include "base/Stream.h" 20 21 #include <assert.h> 22 #include <inttypes.h> 23 #include <stdlib.h> 24 #include <stdio.h> 25 26 class IOStream { 27 protected: IOStream(size_t bufSize)28 explicit IOStream(size_t bufSize) : m_bufsize(bufSize) {} 29 ~IOStream()30 ~IOStream() { 31 // NOTE: m_buf was owned by the child class thus we expect it to be 32 // released before the object destruction. 33 } 34 35 public: 36 virtual void *allocBuffer(size_t minSize) = 0; 37 virtual int commitBuffer(size_t size) = 0; 38 virtual int writeFully(const void* buf, size_t len) = 0; 39 virtual const unsigned char *readFully( void *buf, size_t len) = 0; 40 read(void * buf,size_t bufLen)41 size_t read(void* buf, size_t bufLen) { 42 if (!readRaw(buf, &bufLen)) { 43 return 0; 44 } 45 return bufLen; 46 } 47 alloc(size_t len)48 unsigned char* alloc(size_t len) { 49 if (m_buf && len > m_free) { 50 if (flush() < 0) { 51 ERR("Failed to flush in alloc\n"); 52 return NULL; // we failed to flush so something is wrong 53 } 54 } 55 56 if (!m_buf || len > m_bufsize) { 57 int allocLen = m_bufsize < len ? len : m_bufsize; 58 m_buf = (unsigned char *)allocBuffer(allocLen); 59 if (!m_buf) { 60 ERR("Alloc (%u bytes) failed\n", allocLen); 61 return NULL; 62 } 63 m_bufsize = m_free = allocLen; 64 } 65 66 unsigned char* ptr = m_buf + (m_bufsize - m_free); 67 m_free -= len; 68 69 return ptr; 70 } 71 flush()72 int flush() { 73 if (!m_buf || m_free == m_bufsize) return 0; 74 75 int stat = commitBuffer(m_bufsize - m_free); 76 m_buf = NULL; 77 m_free = 0; 78 return stat; 79 } 80 readback(void * buf,size_t len)81 const unsigned char *readback(void *buf, size_t len) { 82 flush(); 83 return readFully(buf, len); 84 } 85 save(android::base::Stream * stream)86 void save(android::base::Stream* stream) { 87 stream->putBe32(m_bufsize); 88 stream->putBe32(m_free); 89 stream->putByte(m_buf != nullptr); 90 onSave(stream); 91 } 92 load(android::base::Stream * stream)93 void load(android::base::Stream* stream) { 94 m_bufsize = stream->getBe32(); 95 m_free = stream->getBe32(); 96 const bool haveBuf = stream->getByte(); 97 const auto buf = onLoad(stream); 98 m_buf = haveBuf ? buf : nullptr; 99 } 100 101 virtual void* getDmaForReading(uint64_t guest_paddr) = 0; 102 virtual void unlockDma(uint64_t guest_paddr) = 0; 103 104 protected: 105 virtual const unsigned char *readRaw(void *buf, size_t *inout_len) = 0; 106 virtual void onSave(android::base::Stream* stream) = 0; 107 virtual unsigned char* onLoad(android::base::Stream* stream) = 0; 108 109 unsigned char* m_buf = nullptr; 110 size_t m_bufsize; 111 size_t m_free = 0; 112 }; 113