Can the pre compiled contract related to bls12-381 be invoked successfully in the local test environment provided by Remix? - solidity

When I call the precompiled contract, it always returns 0.
Of course, there is more likely to be a problem with my code.
my code:
struct G1Point {
uint256[2] X;
uint256[2] Y;
}
function addition(G1Point memory p1, G1Point memory p2)
internal
view
returns (G1Point memory r)
{
uint256[8] memory input;
input[0] = p1.X[0];
input[1] = p1.X[1];
input[2] = p1.Y[0];
input[3] = p1.Y[1];
input[4] = p2.X[0];
input[5] = p2.X[1];
input[6] = p2.Y[0];
input[7] = p2.Y[1];
bool success;
assembly {
success := staticcall(gas(), 0x0b, input, 256 , r, 0x80)
switch success
case 0 {
invalid()
}
}
require(success, "pairing-add-failed");
}
My English is not good. I hope I have clearly explained the problems I have encountered

Related

How to create MPI performance models using Hockney model parameters?

I understand that the parameters α and β can be used in the Hockney model to represent latency and bandwidth in peer to peer communications with m representing the message size. For example:
T(m) = α + β · m
I have been trying to model some OpenMPI algorithms using this technique and can't figure out this following algorithm for MPI_Scatter:
int
ompi_coll_base_scatter_intra_linear_nb(const void *sbuf, int scount,
struct ompi_datatype_t *sdtype,
void *rbuf, int rcount,
struct ompi_datatype_t *rdtype,
int root,
struct ompi_communicator_t *comm,
mca_coll_base_module_t *module,
int max_reqs)
{
int i, rank, size, err, line, nreqs;
ptrdiff_t incr;
char *ptmp;
ompi_request_t **reqs = NULL, **preq;
rank = ompi_comm_rank(comm);
size = ompi_comm_size(comm);
/* If not root, receive data. */
if (rank != root) {
err = MCA_PML_CALL(recv(rbuf, rcount, rdtype, root,
MCA_COLL_BASE_TAG_SCATTER,
comm, MPI_STATUS_IGNORE));
if (MPI_SUCCESS != err) {
line = __LINE__; goto err_hndl;
}
return MPI_SUCCESS;
}
if (max_reqs <= 1) {
max_reqs = 0;
nreqs = size - 1; /* no send for myself */
} else {
/* We use blocking MPI_Send (which does not need a request)
* every max_reqs send operation (which is size/max_reqs at most),
* therefore no need to allocate requests for these sends. */
nreqs = size - (size / max_reqs);
}
reqs = ompi_coll_base_comm_get_reqs(module->base_data, nreqs);
if (NULL == reqs) {
err = OMPI_ERR_OUT_OF_RESOURCE;
line = __LINE__; goto err_hndl;
}
err = ompi_datatype_type_extent(sdtype, &incr);
if (OMPI_SUCCESS != err) {
line = __LINE__; goto err_hndl;
}
incr *= scount;
/* I am the root, loop sending data. */
for (i = 0, ptmp = (char *)sbuf, preq = reqs; i < size; ++i, ptmp += incr) {
/* simple optimization */
if (i == rank) {
if (MPI_IN_PLACE != rbuf) {
err = ompi_datatype_sndrcv(ptmp, scount, sdtype, rbuf, rcount,
rdtype);
}
} else {
if (!max_reqs || (i % max_reqs)) {
err = MCA_PML_CALL(isend(ptmp, scount, sdtype, i,
MCA_COLL_BASE_TAG_SCATTER,
MCA_PML_BASE_SEND_STANDARD,
comm, preq++));
} else {
err = MCA_PML_CALL(send(ptmp, scount, sdtype, i,
MCA_COLL_BASE_TAG_SCATTER,
MCA_PML_BASE_SEND_STANDARD,
comm));
}
}
if (MPI_SUCCESS != err) {
line = __LINE__; goto err_hndl;
}
}
err = ompi_request_wait_all(preq - reqs, reqs, MPI_STATUSES_IGNORE);
if (MPI_SUCCESS != err) {
line = __LINE__; goto err_hndl;
}
return MPI_SUCCESS;
err_hndl:
if (NULL != reqs) {
/* find a real error code */
if (MPI_ERR_IN_STATUS == err) {
for (i = 0; i < nreqs; i++) {
if (MPI_REQUEST_NULL == reqs[i]) continue;
if (MPI_ERR_PENDING == reqs[i]->req_status.MPI_ERROR) continue;
if (reqs[i]->req_status.MPI_ERROR != MPI_SUCCESS) {
err = reqs[i]->req_status.MPI_ERROR;
break;
}
}
}
ompi_coll_base_free_reqs(reqs, nreqs);
}
OPAL_OUTPUT((ompi_coll_base_framework.framework_output,
"%s:%4d\tError occurred %d, rank %2d", __FILE__, line, err, rank));
(void)line; /* silence compiler warning */
return err;
}
So far I understand that from looking at the code that the model should be
T(NP, m) = (NP − 1) · (α + m · β).
With NP being the number of processes (As Scatter distributes using all processes apart from the root).
This does not account for the use of non-blocking sends that are send using MPI_Isend. (on the condition found in the code snippet) I am unsure of how to account for both the non-blocking and blocking sends using simply the Hockney Model.
Any help would be very much appreciated as non of the papers that I have read on the subject seem to explain the process well.
First of all, the source file mentions that this implementation is probably only for small numbers of processes: for larger numbers you probably want to do something treewise. Next, the max_reqs parameter controls how many isend calls you do before a blocking send call. So the running time of this algorithm would be equal to the number of times you do a blocking send. In an ideal world. In practice, non-blocking sends still have to be serialized out.
My best guess is that this algorithm can handle the case where there are multiple network cards or multiple ports per network card. If you can send 4 messages at a time (physically!) then this code sets up 3 non-blocking & 1 blocking send, and when the blocking send has gone through, your network ports are ready for the next batch of messages.

Disallow copy with functions taking PyBind11 arrays

I have created a function which takes a py::array_t<double> as input.
When calling it from Python, I can pass as input a NumPy array with either float32 or float64 dtype. My issue with this is that if the former dtype is used, it will inevitably incur a "silent" copy of the array in order to coerce it to float64.
I would like to disable all such silent copies (e.g., produce an error if a float32 array is passed).
For the same reason, I would also like to disallow inputs that are not C-contiguous since my function assumes C-contiguity.
Are any of these things possible to do (easily) with PyBind11?
The best that I have found is taking as an argument not
py::array_t<double> &my_object
but instead
py::buffer & my_object
which is more general
Then
py::buffer_info buffer_info = my_object.request();
if( buffer_info.format[0] != 'd') {
throw std::invalid_argument("The argument must be an array of float64");
}
the buffer structure contains ndim, shape, strides, itemsize and more. With that you can check if the array is contiguous, c_style, f_style. The data itself is member void *ptr.
To check contiguity
bool check_c_contiguity(py::buffer_info &info) {
int ndim = info.ndim;
size_t stride = 0;
size_t prod=1;
for(int i=ndim-1; i>=0; i--) {
stride = prod * info.itemsize ;
prod = prod * info.shape[i];
if ( stride != info.strides[i] ) {
return false;
}
}
return true;
}
bool check_f_contiguity(py::buffer_info &info) {
int ndim = info.ndim;
size_t stride = 0;
size_t prod=1;
for(int i=0; i<ndim; i++) {
stride = prod * info.itemsize;
prod = prod * info.shape[i];
if ( stride != info.strides[i] ) {
return false;
}
}
return true;
}

Is there a way to generate 2D stretched mesh using CGAL?

I currently use CGAL to generate 2D Delaunay triangulation.One of the mesh control parameter is the maximum length of the triangle edge. The examples suggests that this parameter is a constant. I would like to know how this parameter be made function of some thing else, for example spatial location.
I think Delaunay meshing with variable density is not directly supported by CGAL although you could mesh your regions independently. Alternatively you may have a look at: http://www.geom.at/advanced-mesh-generation/ where I have implemented that as a callback function.
It doesn't look like CGAL provides an example of this but they machinery is all there. The details get a little complicated since the objects that control if triangles need to be refined also have to understand the priority under which triangles get refined.
To do this, I copied Delaunay_mesh_size_criteria_2 to create a new class (Delaunay_mesh_user_criteria_2) that has a spatially varying sizing field. Buried in the class is a function (user_sizing_field) that can be implemented with a varying size field based on location. The code below compares the size of the longest edge of the triangle to the minimum of the sizing field at the three vertices, but you could use a size at the barycenter or circumcenter or even send the entire triangle to the sizing function if you have a good way to compute the smallest allowable size on the triangle altogether.
This is a starting point, although a better solution would,
refactor some things to avoid so much duplication with with existing Delaunay_mesh_size_criteria,
allow the user to pass in the sizing function as an argument to the criteria object, and
be shipped with CGAL.
template <class CDT>
class Delaunay_mesh_user_criteria_2 :
public virtual Delaunay_mesh_criteria_2<CDT>
{
protected:
typedef typename CDT::Geom_traits Geom_traits;
double sizebound;
public:
typedef Delaunay_mesh_criteria_2<CDT> Base;
Delaunay_mesh_user_criteria_2(const double aspect_bound = 0.125,
const Geom_traits& traits = Geom_traits())
: Base(aspect_bound, traits){}
// first: squared_minimum_sine
// second: size
struct Quality : public std::pair<double, double>
{
typedef std::pair<double, double> Base;
Quality() : Base() {};
Quality(double _sine, double _size) : Base(_sine, _size) {}
const double& size() const { return second; }
const double& sine() const { return first; }
// q1<q2 means q1 is prioritised over q2
// ( q1 == *this, q2 == q )
bool operator<(const Quality& q) const
{
if( size() > 1 )
if( q.size() > 1 )
return ( size() > q.size() );
else
return true; // *this is big but not q
else
if( q.size() > 1 )
return false; // q is big but not *this
return( sine() < q.sine() );
}
std::ostream& operator<<(std::ostream& out) const
{
return out << "(size=" << size()
<< ", sine=" << sine() << ")";
}
};
class Is_bad: public Base::Is_bad
{
public:
typedef typename Base::Is_bad::Point_2 Point_2;
Is_bad(const double aspect_bound,
const Geom_traits& traits)
: Base::Is_bad(aspect_bound, traits) {}
Mesh_2::Face_badness operator()(const Quality q) const
{
if( q.size() > 1 )
return Mesh_2::IMPERATIVELY_BAD;
if( q.sine() < this->B )
return Mesh_2::BAD;
else
return Mesh_2::NOT_BAD;
}
double user_sizing_function(const Point_2 p) const
{
// IMPLEMENT YOUR CUSTOM SIZING FUNCTION HERE.
// BUT MAKE SURE THIS RETURNS SOMETHING LARGER
// THAN ZERO TO ALLOW THE ALGORITHM TO TERMINATE
return std::abs(p.x()) + .025;
}
Mesh_2::Face_badness operator()(const typename CDT::Face_handle& fh,
Quality& q) const
{
typedef typename CDT::Geom_traits Geom_traits;
typedef typename Geom_traits::Compute_area_2 Compute_area_2;
typedef typename Geom_traits::Compute_squared_distance_2 Compute_squared_distance_2;
Geom_traits traits; /** #warning traits with data!! */
Compute_squared_distance_2 squared_distance =
traits.compute_squared_distance_2_object();
const Point_2& pa = fh->vertex(0)->point();
const Point_2& pb = fh->vertex(1)->point();
const Point_2& pc = fh->vertex(2)->point();
double size_bound = std::min(std::min(user_sizing_function(pa),
user_sizing_function(pb)),
user_sizing_function(pc));
double
a = CGAL::to_double(squared_distance(pb, pc)),
b = CGAL::to_double(squared_distance(pc, pa)),
c = CGAL::to_double(squared_distance(pa, pb));
double max_sq_length; // squared max edge length
double second_max_sq_length;
if(a<b)
{
if(b<c) {
max_sq_length = c;
second_max_sq_length = b;
}
else { // c<=b
max_sq_length = b;
second_max_sq_length = ( a < c ? c : a );
}
}
else // b<=a
{
if(a<c) {
max_sq_length = c;
second_max_sq_length = a;
}
else { // c<=a
max_sq_length = a;
second_max_sq_length = ( b < c ? c : b );
}
}
q.second = 0;
q.second = max_sq_length / (size_bound*size_bound);
// normalized by size bound to deal
// with size field
if( q.size() > 1 )
{
q.first = 1; // (do not compute sine)
return Mesh_2::IMPERATIVELY_BAD;
}
Compute_area_2 area_2 = traits.compute_area_2_object();
double area = 2*CGAL::to_double(area_2(pa, pb, pc));
q.first = (area * area) / (max_sq_length * second_max_sq_length); // (sine)
if( q.sine() < this->B )
return Mesh_2::BAD;
else
return Mesh_2::NOT_BAD;
}
};
Is_bad is_bad_object() const
{ return Is_bad(this->bound(), this->traits /* from the bad class */); }
};
I am also interested for variable mesh criteria on the domaine with CGAL. I have found an alternative many years ago : https://www.cs.cmu.edu/~quake/triangle.html
But i am still interested to do the same things with CGAL ... I don't know if it is possible ...

Dynamic Bytecode Instrumentation fails without any error

Objective
I'm doing dynamic bytecode instrumentation using a JVMTI agent. I have to instrument those methods which are "hot", that is, the methods which invoke JIT compiler. To do so I listen to a CompiledLoadEvent and inside its call back function, call RetransformClasses. This in turn invokes ClassFileLoadHook on the class containing "hot" function and actual instrumentation begins.
Problem Premises
Currently I'm instrumenting my class to spawn some threads. I also listen to thread starts and print them within my agent. With simple ClassFileLoadHook at class load time (without RetransformClasses), my instrumentation works perfectly and spawns new threads. I get following output when ClassFileLoadHook instruments at class load time:
Running Thread: Signal Dispatcher, Priority: 9, context class loader:Not Null
Running Thread: main, Priority: 5, context class loader:Not Null
Running Thread: Thread-0, Priority: 5, context class loader:Not Null
Running Thread: Thread-1, Priority: 5, context class loader:Not Null
Running Thread: Thread-2, Priority: 5, context class loader:Not Null
Running Thread: Thread-3, Priority: 5, context class loader:Not Null
Running Thread: Thread-4, Priority: 5, context class loader:Not Null
Running Thread: Thread-6, Priority: 5, context class loader:Not Null
Running Thread: Thread-5, Priority: 5, context class loader:Not Null
Running Thread: Thread-7, Priority: 5, context class loader:Not Null
Running Thread: DestroyJavaVM, Priority: 5, context class loader:: NULL
When I instrument the class file by invoking RetransformClasses and then ClassFileLoadHook, everything works fine but no threads are spawned and hence no effective instrumentation takes place. VM takes a long time even to execute the original code.
I double checked both instrumentations using -XX:+TraceClassLoading. All the retransformed classes are loaded in both cases. Even the class I'm generating during runtime also gets loaded but no instrumentation happens. Below is the output of class loading trace:
[Loaded Test from __VM_RedefineClasses__]
[Loaded Test_Worker_main_0 from file:/home/saqib/workspace/test/bin]
I'm generating second class during runtime and it loads into VM but I don't get any thread spawning.
Questions
Given my understanding of the problem (There is a high probability
that I'd be wrong), why ClassFileLoadHook retransforms the class
successfully during load time, but somehow doesn't behave correctly
when JIT is invoked?
Just writing the RetransformClasses function, with empty
ClassFileLoadHook call back, also takes a lot of time without
incurring any sort of error. What could be taking time?
Agent Code
Compiled Load Event Call Back
static int x = 1;
void JNICALL
compiled_method_load(jvmtiEnv *jvmti, jmethodID method, jint code_size,
const void* code_addr, jint map_length, const jvmtiAddrLocationMap* map,
const void* compile_info) {
jvmtiError err;
jclass klass;
char* name = NULL;
char* signature = NULL;
char* generic_ptr = NULL;
err = (*jvmti)->RawMonitorEnter(jvmti, lock);
check_jvmti_error(jvmti, err, "raw monitor enter");
err = (*jvmti)->GetMethodName(jvmti, method, &name, &signature,
&generic_ptr);
check_jvmti_error(jvmti, err, "Get Method Name");
printf("\nCompiled method load event\n");
printf("Method name %s %s %s\n\n", name, signature,
generic_ptr == NULL ? "" : generic_ptr);
if (strstr(name, "main") != NULL && x == 1) {
x++;
err = (*jvmti)->GetMethodDeclaringClass(jvmti, method, &klass);
check_jvmti_error(jvmti, err, "Get Declaring Class");
err = (*jvmti)->RetransformClasses(jvmti, 1, &klass);
check_jvmti_error(jvmti, err, "Retransform class");
}
if (name != NULL) {
err = (*jvmti)->Deallocate(jvmti, (unsigned char*) name);
check_jvmti_error(jvmti, err, "deallocate name");
}
if (signature != NULL) {
err = (*jvmti)->Deallocate(jvmti, (unsigned char*) signature);
check_jvmti_error(jvmti, err, "deallocate signature");
}
if (generic_ptr != NULL) {
err = (*jvmti)->Deallocate(jvmti, (unsigned char*) generic_ptr);
check_jvmti_error(jvmti, err, "deallocate generic_ptr");
}
err = (*jvmti)->RawMonitorExit(jvmti, lock);
check_jvmti_error(jvmti, err, "raw monitor exit");
}
Class File Load Hook
void JNICALL
Class_File_Load_Hook(jvmtiEnv *jvmti_env, JNIEnv* jni_env,
jclass class_being_redefined, jobject loader, const char* name,
jobject protection_domain, jint class_data_len,
const unsigned char* class_data, jint* new_class_data_len,
unsigned char** new_class_data) {
jvmtiError err;
unsigned char* jvmti_space = NULL;
if (strstr(name, "Test") != NULL && x == 2) {
char* args = "op";
javab_main(2, args, class_data, class_data_len);
err = (*jvmti_env)->Allocate(jvmti_env, (jlong)global_pos, &jvmti_space);
check_jvmti_error(jvmti_env, err, "Allocate new class Buffer.");
(void)memcpy((void*)jvmti_space, (void*)new_class_ptr, (int)global_pos);
*new_class_data_len = (jint)global_pos;
*new_class_data = jvmti_space;
if ( new_class_ptr != NULL ) {
(void)free((void*)new_class_ptr);
}
#if DEBUG
printf("Size of the class is: %d\n", class_data_len);
for (int i = 0; i < class_data_len; i += 4) {
if (i % 16 == 0)
printf("\n");
printf("%02x%02x %02x%02x ", new_class_data[i],
new_class_data[i + 1], new_class_data[i + 2],
new_class_data[i + 3]);
}
printf("\n");
system("javap -c -v Test_debug");
#endif
x++;
}
}
Here javab_main returns the instrumented char * array which is correct. The instrumented array is stored in a global variable new_class_ptr which is copied into new_class_data. To debug the output of the instrumentation, I also printed the instrumented class in a file called Test_debug and invoking javap on it produces desired result.
The complete agent file is given here:
Agent.c
Original Code:
for (int i = 0; i < s; i++)
for (int j = 0; j < s; j++) {
c2[i][j] = 0;
for (int k = 0; k < s; k++)
c2[i][j] += a[i][k] * b[k][j];
}
Instrumented Code: (Equivalent)
Thread[] threads = new Thread[NTHREADS];
for (int i = 0; i < NTHREADS ; i++) {
final int lb = i * SIZE/NTHREADS;
final int ub = (i+1) * SIZE/NTHREADS;
threads[i] = new Thread(new Runnable() {
public void run() {
for (int i = lb; i < ub; i++)
for (int j = 0; j < SIZE; j++) {
c2[i][j] = 0;
for (int k = 0; k < SIZE; k++)
c2[i][j] += a[i][k] * b[k][j];
}
}
});
threads[i].start();
}
// wait for completion
for (int i = 0; i < NTHREADS; i++) {
try {
threads[i].join();
} catch (InterruptedException ignore) {
}
}
Java Version
openjdk version "1.8.0-internal-debug"
OpenJDK Runtime Environment (build 1.8.0-internal-debug-saqib_2016_12_26_10_52-b00)
OpenJDK 64-Bit Server VM (build 25.71-b00-debug, mixed mode)
I'm constructing this answer mainly from the comments. There are still some riddles unsolved but the main question has been resolved. Bytecode instrumentation does not fail in my case. It actually never happens. According to the theory,
Dynamic bytecode instrumentation of an executing function takes place
at subsequent call of the function. If a function has only one invocation, it cannot be instrumented while execution using current hotswap techniques in JVM.
I was trying to instrument a class which had only one function, i.e. main. I was trying to instrument that during runtime. This was the main problem. To check the validity of this argument, I tried to put my code in another function and called it from main in a loop. It got instrumented and everything worked. Nothing has to be changed in the agent.

How to read_single_block from SD card using SPI mode (getting weird behavior as of yet)?

When I issue cmd17 with address (0x00000000) to my card from PIC-18F4520 on SPI bus, I get a correct return R1 token from the command issue. Then, after a few loops checking, I get a 0xFE marker returned from my issuing SPI_Put_Char(0xFF). Data should then start so I read 512 bytes into my IO_Buffer array. As I scan the returns, I got many 0x00 bytes. Oddly, and repeatedly, at about pos 448 in sector 0, some data comes over - a few bytes here and there - then the the final 32 bytes (I can only view 32 at a time on my LCD screen) are all zeroes followed by the 0x55AA marker expected at the end of the boot sector.
The odd thing, is that using disk investigator reveals the SD card has the proper sector zero information - MSDOS message, EB jump code, all sorts of stuff. My read command gives all that back as zeroes. I just don't get what's happening.
Other information: I boot with the cmd0, cmd8, cmd58 and OCR reads fine. Then acmd41 (looping cmd55 followed by APP_SEND_OP_COND). All seem to respond and give expected marker. Finally, I even use SEND_CID to get the card information. that returns MID=3 OID=SD and a verion SD017 followed by other information - seems all to be correct.
I have tried adding pull up and pull down resistors on DOUT from card but doesn't affect any results.
I am desperate for ideas to try to get this card to read correctly. I have (BTW) tried two other cards. They give different specific results, but qualitatively the same - initialization, OCR, and CID read all work okay. Data read gives mostly zeroes followed by some reproducible but sparse bytes, and a 0xAA55 marker!?!
My SanDisk 1GB SD card is running at 3.296 volts which seems stable during card reading.
Here's some code:
bit MMC_Command(unsigned char cmd, unsigned short AdrH, unsigned short AdrL, unsigned char *response)
{
unsigned char response_length;
unsigned char MMC_Counter_Byte = 255;
unsigned char current_response;
switch (cmd)
{
case MMC_SEND_IF_COND:
case MMC_READ_OCR:
response_length = 5;
break;
case MMC_SEND_STATUS:
response_length = 2;
break;
default:
response_length = 1;
};
DEV_xSELECT = DEV_MMC;
SPI_Put_Char(cmd);
SPI_Put_Char(AdrH >> 8);
SPI_Put_Char(AdrH & 0x00FFU);
SPI_Put_Char(AdrL >> 8);
SPI_Put_Char(AdrL & 0x00FFU);
SPI_Put_Char(0x95U); //CRC = 0x95 to get to SPI, then value not important, so always use this for convenience
do
{
response[0] = SPI_Put_Char(0xFF);
} while ((response[0] & 0x80) && --MMC_Counter_Byte);
if (!MMC_Counter_Byte)
{
//SPI_Put_Char(0xFF); //some say is necessary
DEV_xSELECT = DEV_NONE;
return FALSE;
};
for (current_response = 1; current_response < response_length; current_response++)
{
response[current_response] = SPI_Put_Char(0xFF);
};
SPI_Put_Char(0xFF); //some say is necessary
DEV_xSELECT = DEV_NONE;
return TRUE;
};
unsigned char MMC_Init_SD(void)
{
unsigned long MMC_Counter_Word;
unsigned char response[5];
DEV_xSELECT = DEV_MMC;
for (MMC_Counter_Word = 0; MMC_Counter_Word < 20; MMC_Counter_Word++)
{
SPI_Put_Char(0xFFU);
};
DEV_xSELECT = DEV_NONE;
for (MMC_Counter_Word = 0; MMC_Counter_Word < 10; MMC_Counter_Word++)
{
SPI_Put_Char(0xFFU);
};
MMC_Counter_Word = 255;
do
{
MMC_Command(MMC_GO_IDLE_STATE, 0x0000, 0x0000, response); //cmd0
} while (--MMC_Counter_Word && (response[0] != 0x01));
if (!MMC_Counter_Word) //if counter timed out, error
{
return FALSE;
};
MMC_Command(MMC_SEND_IF_COND, 0x0000, 0x01AA, response); //cmd8
if (response[0] != 0x05)
{
return FALSE; //other card type
};
MMC_Command(MMC_READ_OCR, 0x0000, 0x0000, response); //cmd58
MMC_Counter_Word = 0xFFFFU;
do
{
if (MMC_Command(MMC_APP_CMD, 0x0000, 0x0000, response)) //cmd55
{
MMC_Command(MMC_APP_SEND_OP_COND, 0x4001, 0x0000, response); //acmd41
SPI_Put_Char(0xFF);
}
else
{
return FALSE;
};
} while (--MMC_Counter_Word && ((response[0] & 1) == 1));
if (!MMC_Counter_Word)
{
return FALSE;
};
if (MMC_Command(MMC_SEND_CID, 0x0000, 0x0000, response)) //cmd10
{
DEV_xSELECT = DEV_MMC;
MMC_Counter_Word = 255;
while (--MMC_Counter_Word && (SPI_Put_Char(0xFF) != 0xFE));
if (!MMC_Counter_Word)
{
DEV_xSELECT = DEV_NONE;
return FALSE;
};
//code for reading 16 byte OCR goes here
SPI_Put_Char(0xFFU);
SPI_Put_Char(0xFFU); //cycle through 16-bit CRC
SPI_Put_Char(0xFFU); //1GB Sandisk SD seems to require another dummy
DEV_xSELECT = DEV_NONE;
Delay_Sec(2);
LCD_CLS();
}
else
{
return FALSE;
};
return TRUE;
};
bit MMC_Fill_IO_Buffer(unsigned long sector)
{
unsigned short MMC_Fill_Index_Byte;
unsigned char MMC_Counter_Byte = 255;
unsigned char response[1];
if (MMC_Command(MMC_READ_SINGLE_BLOCK, 0x0000, 0x0000, response)) //cmd10
{
DEV_xSELECT = DEV_MMC;
MMC_Counter_Byte = 255;
while (--MMC_Counter_Byte && (SPI_Put_Char(0xFF) != 0xFE));
if (!MMC_Counter_Byte)
{
DEV_xSELECT = DEV_NONE;
return FALSE;
};
}
else
{
return FALSE;
};
for (MMC_Fill_Index_Byte = 0; MMC_Fill_Index_Byte < 512 ; MMC_Fill_Index_Byte++)
{
IO_Buffer[MMC_Fill_Index_Byte] = SPI_Put_Char(0xFF);
};
SPI_Put_Char(0xFFU);
SPI_Put_Char(0xFFU); //cycle through 16-bit CRC
SPI_Put_Char(0xFFU); //1GB Sandisk SD seems to require another dummy
DEV_xSELECT = DEV_NONE;
//following is IO_Buffer displaying code.
//LCD_CLS();
//for (MMC_Counter_Byte = 0; MMC_Counter_Byte < 42; MMC_Counter_Byte++)
//{
// LCD_Draw_Byte_Hex(IO_Buffer[MMC_Counter_Byte + 448]);
//};
//while (1);
return TRUE;
};
Thanks ahead of time!
Your sector 0 looks like a vaild partition table. If you read from the drive letter using disk investigator you may ended up reading the sector 0 of the partition and not from the sd-card itself. This program does not seem to be able to read from a physical device, so you can not use it to read the partition table.
Finally found the solution to this!
It turns out you were reading the MBR, which is located at the address 0 on the SD card. To find the location of the boot sector, one needs to read the appropriate entry in the MBR. The entries start at the address 0x01be and are 16 bytes each. The point of interest in the entry lies at the offset 0x08, is 4 bytes long and is called an LBA. [Wikipedia] To get the address of the boot sector location, one would multiply the LBA by the size of a sector (512 bytes). [Microchip forum]
For an example, see my other answer.